private SDProperty GetParsedProperty(IPropertySymbol property) { var syntaxReference = property.DeclaringSyntaxReferences.Any() ? property.DeclaringSyntaxReferences.Single() : null; var sdProperty = new SDProperty(property.GetIdentifier()) { Name = property.Name, DeclaringType = _typeRefParser.GetParsedTypeReference(property.ContainingType), Accessibility = property.DeclaredAccessibility.ToString().ToLower(), ReturnType = _typeRefParser.GetParsedTypeReference(property.Type), CanGet = property.GetMethod != null, CanSet = property.SetMethod != null, IsAbstract = property.IsAbstract, IsVirtual = property.IsVirtual, IsOverride = property.IsOverride, Documentations = DocumentationParser.ParseDocumentation(property), Region = syntaxReference != null ? new SDRegion { Start = syntaxReference.Span.Start, End = syntaxReference.Span.End, StartLine = syntaxReference.SyntaxTree.GetLineSpan(syntaxReference.Span).StartLinePosition.Line + 1, EndLine = syntaxReference.SyntaxTree.GetLineSpan(syntaxReference.Span).EndLinePosition.Line + 1, FilePath = syntaxReference.SyntaxTree.FilePath, Filename = Path.GetFileName(syntaxReference.SyntaxTree.FilePath) } : null }; ParserOptions.SDRepository.AddMember(sdProperty); return sdProperty; }
private IMethodSymbol GenerateSetAccessor( Compilation compilation, IPropertySymbol property, Accessibility accessibility, bool generateAbstractly, bool useExplicitInterfaceSymbol, INamedTypeSymbol[] attributesToRemove, CancellationToken cancellationToken) { if (property.SetMethod == null) { return null; } var setMethod = property.SetMethod.RemoveInaccessibleAttributesAndAttributesOfTypes( this.State.ClassOrStructType, attributesToRemove); return CodeGenerationSymbolFactory.CreateAccessorSymbol( setMethod, attributes: null, accessibility: accessibility, explicitInterfaceSymbol: useExplicitInterfaceSymbol ? property.SetMethod : null, statements: GetSetAccessorStatements(compilation, property, generateAbstractly, cancellationToken)); }
internal static IPropertySymbol CreatePropertySymbol( INamedTypeSymbol containingType, IList<AttributeData> attributes, Accessibility accessibility, DeclarationModifiers modifiers, ITypeSymbol type, IPropertySymbol explicitInterfaceSymbol, string name, IList<IParameterSymbol> parameters, IMethodSymbol getMethod, IMethodSymbol setMethod, bool isIndexer = false, SyntaxNode initializer = null) { var result = new CodeGenerationPropertySymbol( containingType, attributes, accessibility, modifiers, type, explicitInterfaceSymbol, name, isIndexer, parameters, getMethod, setMethod); CodeGenerationPropertyInfo.Attach(result, modifiers.IsNew, modifiers.IsUnsafe, initializer); return result; }
public virtual SimilarityRank<IPropertySymbol> FindSimilarityRank(IPropertySymbol sourceProperty, IEnumerable<IPropertySymbol> targetProperties, List<IClassPropertyComparer> allComparers) { var allMatches = FindAllMatches(sourceProperty, targetProperties, allComparers); var topMatch = allMatches.OrderByDescending(r => r.Confidence).FirstOrDefault(r => r.Confidence > 0); return (topMatch ?? new SimilarityRank<IPropertySymbol>()); }
internal void HandleValueField(ValueField valueField, IPropertySymbol property, ImmutableArray<AttributeData> propertyAttributes) { AddKeyAttribute(property, propertyAttributes, valueField); AddIndexAttribute(property, propertyAttributes, valueField); AddMaxLengthAttribute(property, propertyAttributes, valueField); AddDatabaseGeneratedAttribute(property, propertyAttributes, valueField); }
public static void Create(IPropertySymbol symbol, SymbolKeyWriter visitor) { visitor.WriteString(symbol.MetadataName); visitor.WriteSymbolKey(symbol.ContainingSymbol); visitor.WriteBoolean(symbol.IsIndexer); visitor.WriteRefKindArray(symbol.Parameters); visitor.WriteParameterTypesArray(symbol.OriginalDefinition.Parameters); }
public static void Attach( IPropertySymbol property, bool isNew, bool isUnsafe) { var info = new CodeGenerationPropertyInfo(isNew, isUnsafe); propertyToInfoMap.Add(property, info); }
public SimilarityRank<IPropertySymbol> Compare(IPropertySymbol sourceProperty, IPropertySymbol targetProperty) { //TODO: check for subclasses bool sameType = sourceProperty.Type.Equals(targetProperty.Type); int confidence = (sameType ? 100 : 0); return new SimilarityRank<IPropertySymbol>() { Confidence = confidence, Symbol = targetProperty }; }
public static void Attach( IPropertySymbol property, bool isNew, bool isUnsafe, SyntaxNode initializer) { var info = new CodeGenerationPropertyInfo(isNew, isUnsafe, initializer); s_propertyToInfoMap.Add(property, info); }
public static bool HaveSameSignature (IPropertySymbol property1, IPropertySymbol property2, bool caseSensitive) { try { return (bool)haveSameSignature2Method.Invoke(instance, new object[] { property1, property2, caseSensitive }); } catch (TargetInvocationException ex) { ExceptionDispatchInfo.Capture(ex.InnerException).Throw(); return false; } }
protected override void ReadSymbol(IPropertySymbol propertySymbol) { // we don't need to know about static members // because they won't be delegated from child to mixin if (propertySymbol.IsStatic) return; // we ignore private and protected memebers var hasGetter = propertySymbol.GetMethod != null && !(propertySymbol.GetMethod.DeclaredAccessibility == Accessibility.Private || propertySymbol.GetMethod.DeclaredAccessibility == Accessibility.Protected); var hasSetter = propertySymbol.SetMethod != null && !(propertySymbol.SetMethod.DeclaredAccessibility == Accessibility.Private || propertySymbol.SetMethod.DeclaredAccessibility == Accessibility.Protected); // property has no accessors or accessors are not accessible => skip property if (!hasSetter && !hasGetter) return; Property property = null; if (propertySymbol.IsIndexer) // symbol is an indexer property { var indexerProperty = new IndexerProperty( propertySymbol.Type, hasGetter, hasSetter); var parameterReader = new ParameterSymbolReader(indexerProperty); parameterReader.VisitSymbol(propertySymbol); property = indexerProperty; } else // symbol is a normal property { property = new Property( propertySymbol.Name, propertySymbol.Type, hasGetter, hasSetter); } property.IsAbstract = propertySymbol.IsAbstract; property.IsOverride = propertySymbol.IsOverride; // store information if accessors are internal, // we will need this for the generation later property.IsGetterInternal = hasGetter && propertySymbol.GetMethod .DeclaredAccessibility.HasFlag(Accessibility.Internal); property.IsSetterInternal = hasSetter && propertySymbol.SetMethod .DeclaredAccessibility.HasFlag(Accessibility.Internal); property.Documentation = new DocumentationComment(propertySymbol.GetDocumentationCommentXml()); _properties.AddProperty(property); }
private List<SimilarityRank<IPropertySymbol>> FindAllMatches(IPropertySymbol sourceProperty, IEnumerable<IPropertySymbol> targetProperties, List<IClassPropertyComparer> allComparers) { var allMatches = new List<SimilarityRank<IPropertySymbol>>(); foreach (var comparer in allComparers) { allMatches.AddRange(FindMatches(sourceProperty, targetProperties, comparer)); } return allMatches; }
internal static CompilationUnitSyntax AddPropertyTo( CompilationUnitSyntax destination, IPropertySymbol property, CodeGenerationOptions options, IList<bool> availableIndices) { var declaration = GeneratePropertyOrIndexer(property, CodeGenerationDestination.CompilationUnit, options); var members = Insert(destination.Members, declaration, options, availableIndices, after: LastPropertyOrField, before: FirstMember); return destination.WithMembers(members); }
private SimilarityRank<IPropertySymbol> CompoundCompare(IPropertySymbol sourceProperty, IPropertySymbol targetProperty, IEnumerable<IClassPropertyComparer> comparers) { List<SimilarityRank<IPropertySymbol>> allResultRanks = new List<SimilarityRank<IPropertySymbol>>(); foreach (var propertyComparer in comparers) { SimilarityRank<IPropertySymbol> rank = propertyComparer.Compare(sourceProperty, targetProperty); allResultRanks.Add(rank); } return BuildCombinedRank(targetProperty, allResultRanks); }
private ISymbol GenerateProperty( Compilation compilation, IPropertySymbol property, Accessibility accessibility, DeclarationModifiers modifiers, bool generateAbstractly, bool useExplicitInterfaceSymbol, string memberName, CancellationToken cancellationToken) { var factory = this.Document.GetLanguageService<SyntaxGenerator>(); var comAliasNameAttribute = compilation.ComAliasNameAttributeType(); var getAccessor = property.GetMethod == null ? null : CodeGenerationSymbolFactory.CreateAccessorSymbol( property.GetMethod.RemoveInaccessibleAttributesAndAttributesOfType( accessibleWithin: this.State.ClassOrStructType, removeAttributeType: comAliasNameAttribute), attributes: null, accessibility: accessibility, explicitInterfaceSymbol: useExplicitInterfaceSymbol ? property.GetMethod : null, statements: GetGetAccessorStatements(compilation, property, generateAbstractly, cancellationToken)); var setAccessor = property.SetMethod == null ? null : CodeGenerationSymbolFactory.CreateAccessorSymbol( property.SetMethod.RemoveInaccessibleAttributesAndAttributesOfType( accessibleWithin: this.State.ClassOrStructType, removeAttributeType: comAliasNameAttribute), attributes: null, accessibility: accessibility, explicitInterfaceSymbol: useExplicitInterfaceSymbol ? property.SetMethod : null, statements: GetSetAccessorStatements(compilation, property, generateAbstractly, cancellationToken)); var syntaxFacts = Document.GetLanguageService<ISyntaxFactsService>(); var parameterNames = NameGenerator.EnsureUniqueness( property.Parameters.Select(p => p.Name).ToList(), isCaseSensitive: syntaxFacts.IsCaseSensitive); var updatedProperty = property.RenameParameters(parameterNames); updatedProperty = updatedProperty.RemoveAttributeFromParameters(comAliasNameAttribute); // TODO(cyrusn): Delegate through throughMember if it's non-null. return CodeGenerationSymbolFactory.CreatePropertySymbol( updatedProperty, accessibility: accessibility, modifiers: modifiers, explicitInterfaceSymbol: useExplicitInterfaceSymbol ? property : null, name: memberName, getMethod: getAccessor, setMethod: setAccessor); }
internal ForEachSymbols(IMethodSymbol getEnumeratorMethod, IMethodSymbol moveNextMethod, IPropertySymbol currentProperty, IMethodSymbol disposeMethod, ITypeSymbol elementType) : this() { this.GetEnumeratorMethod = getEnumeratorMethod; this.MoveNextMethod = moveNextMethod; this.CurrentProperty = currentProperty; this.DisposeMethod = disposeMethod; this.ElementType = elementType; }
public bool HaveSameSignature(IPropertySymbol property1, IPropertySymbol property2, bool caseSensitive) { if (!IdentifiersMatch(property1.Name, property2.Name, caseSensitive) || property1.Parameters.Length != property2.Parameters.Length || property1.IsIndexer != property2.IsIndexer) { return false; } return property1.Parameters.SequenceEqual( property2.Parameters, this.ParameterEquivalenceComparer); }
private void AddHasForeignKeyAttribute(IPropertySymbol classProperty, IEnumerable<AttributeData> propertyAttributes, SingleField singleField) { var foreignKeyAttribute = propertyAttributes.SingleOrDefault(a => a.AttributeClass.Name == "HasForeignKeyAttribute"); var foreignKeyAttributeString = "-"; if (foreignKeyAttribute != null) { foreignKeyAttributeString = (string)foreignKeyAttribute.ConstructorArguments[0].Value; } var assumption = _constraintBuilder.Assume(() => singleField.ForeignKeyAttribute == foreignKeyAttributeString); _propertyAssumptions.Add(new HasForeignKeyAttributePropertyAssumption(classProperty, assumption, singleField)); }
private void AddDatabaseGeneratedAttribute(IPropertySymbol classProperty, IEnumerable<AttributeData> propertyAttributes, ValueField valueField) { var databaseGeneratedAttributeValue = DatabaseGeneratedAttribute.None; var databaseGeneratedAttribute = propertyAttributes.SingleOrDefault(a => a.AttributeClass.Name == "DatabaseGeneratedAttribute"); if (databaseGeneratedAttribute != null) { var databaseGeneratedOption = Enum.GetName(typeof(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption), databaseGeneratedAttribute.ConstructorArguments[0].Value); databaseGeneratedAttributeValue = (DatabaseGeneratedAttribute)Enum.Parse(typeof(DatabaseGeneratedAttribute), databaseGeneratedOption); } var assumption = _constraintBuilder.Assume(() => valueField.DatabaseGeneratedAttribute == databaseGeneratedAttributeValue); _propertyAssumptions.Add(new DatabaseGeneratedAttributePropertyAssumption(classProperty, assumption, valueField)); }
/// <summary> /// Creates a property symbol that can be used to describe a property declaration. /// </summary> public static IPropertySymbol CreatePropertySymbol(IList<AttributeData> attributes, Accessibility accessibility, DeclarationModifiers modifiers, ITypeSymbol type, IPropertySymbol explicitInterfaceSymbol, string name, IList<IParameterSymbol> parameters, IMethodSymbol getMethod, IMethodSymbol setMethod, bool isIndexer = false) { return CreatePropertySymbol( containingType: null, attributes: attributes, accessibility: accessibility, modifiers: modifiers, type: type, explicitInterfaceSymbol: explicitInterfaceSymbol, name: name, parameters: parameters, getMethod: getMethod, setMethod: setMethod, isIndexer: isIndexer); }
private List<SimilarityRank<IPropertySymbol>> FindMatches(IPropertySymbol sourceProperty, IEnumerable<IPropertySymbol> targetProperties, IClassPropertyComparer comparer) { var allMatches = new List<SimilarityRank<IPropertySymbol>>(); foreach (var targetProperty in targetProperties) { var rank = comparer.Compare(sourceProperty, targetProperty); if (rank.Confidence > 0) { allMatches.Add(rank); } } return allMatches; }
private async Task<Solution> ReplacePropertyWithMethodsAsync( Document document, IPropertySymbol propertySymbol, CancellationToken cancellationToken) { var desiredMethodSuffix = NameGenerator.GenerateUniqueName(propertySymbol.Name, n => !HasAnyMatchingGetOrSetMethods(propertySymbol, n)); var desiredGetMethodName = GetPrefix + desiredMethodSuffix; var desiredSetMethodName = SetPrefix + desiredMethodSuffix; var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var originalSolution = document.Project.Solution; var propertyReferences = await SymbolFinder.FindReferencesAsync(propertySymbol, originalSolution, cancellationToken).ConfigureAwait(false); // Get the warnings we'd like to put at the definition site. var definitionWarning = GetDefinitionIssues(propertyReferences); var equalityComparer = (IEqualityComparer<IPropertySymbol>)SymbolEquivalenceComparer.Instance; var definitionToBackingField = propertyReferences.Select(r => r.Definition) .OfType<IPropertySymbol>() .ToDictionary(d => d, GetBackingField, equalityComparer); var q = from r in propertyReferences where r.Definition is IPropertySymbol from loc in r.Locations select (property: (IPropertySymbol)r.Definition, location: loc); var referencesByDocument = q.ToLookup(t => t.location.Document); // References and definitions can overlap (for example, references to one property // inside the definition of another). So we do a multi phase rewrite. We first // rewrite all references to point at the new methods instead. Then we remove all // the actual property definitions and replace them with the new methods. var updatedSolution = originalSolution; updatedSolution = await UpdateReferencesAsync( updatedSolution, referencesByDocument, definitionToBackingField, desiredGetMethodName, desiredSetMethodName, cancellationToken).ConfigureAwait(false); updatedSolution = await ReplaceDefinitionsWithMethodsAsync( originalSolution, updatedSolution, propertyReferences, definitionToBackingField, desiredGetMethodName, desiredSetMethodName, cancellationToken).ConfigureAwait(false); return updatedSolution; }
internal static TypeDeclarationSyntax AddPropertyTo( TypeDeclarationSyntax destination, IPropertySymbol property, CodeGenerationOptions options, IList<bool> availableIndices) { var declaration = GeneratePropertyOrIndexer(property, GetDestination(destination), options); // Create a clone of the original type with the new method inserted. var members = Insert(destination.Members, declaration, options, availableIndices, after: LastPropertyOrField, before: FirstMember); // Find the best place to put the field. It should go after the last field if we already // have fields, or at the beginning of the file if we don't. return AddMembersTo(destination, members); }
public static ChangeType CompareTo(this IPropertySymbol symbol, IPropertySymbol comparedTo) { if (symbol == null) return ChangeType.Added; if (comparedTo == null) return ChangeType.Deleted; if (symbol.Type != comparedTo.Type) return ChangeType.Rewritten; if (symbol.DeclaredAccessibility != comparedTo.DeclaredAccessibility) return ChangeType.Rewritten; return ChangeType.None; }
private static MemberDeclarationSyntax GenerateIndexerDeclaration( IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) { var explicitInterfaceSpecifier = GenerateExplicitInterfaceSpecifier(property.ExplicitInterfaceImplementations); return AddCleanupAnnotationsTo( AddAnnotationsTo(property, SyntaxFactory.IndexerDeclaration( attributeLists: AttributeGenerator.GenerateAttributeLists(property.GetAttributes(), options), modifiers: GenerateModifiers(property, destination, options), type: property.Type.GenerateTypeSyntax(), explicitInterfaceSpecifier: explicitInterfaceSpecifier, parameterList: ParameterGenerator.GenerateBracketedParameterList(property.Parameters, explicitInterfaceSpecifier != null, options), accessorList: GenerateAccessorList(property, destination, options)))); }
/// <summary> /// Initializes a new instance of the <see cref="CommonForEachStatementInfo" /> structure. /// </summary> internal CommonForEachStatementInfo(IMethodSymbol getEnumeratorMethod, IMethodSymbol moveNextMethod, IPropertySymbol currentProperty, IMethodSymbol disposeMethod, ITypeSymbol elementType, CommonConversion elementConversion, CommonConversion currentConversion) : this() { this.GetEnumeratorMethod = getEnumeratorMethod; this.MoveNextMethod = moveNextMethod; this.CurrentProperty = currentProperty; this.DisposeMethod = disposeMethod; this.ElementType = elementType; this.ElementConversion = elementConversion; this.CurrentConversion = currentConversion; }
public static MemberDeclarationSyntax GeneratePropertyOrIndexer( IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) { var reusableSyntax = GetReuseableSyntaxNodeForSymbol<MemberDeclarationSyntax>(property, options); if (reusableSyntax != null) { return reusableSyntax; } var declaration = property.IsIndexer ? GenerateIndexerDeclaration(property, destination, options) : GeneratePropertyDeclaration(property, destination, options); return ConditionallyAddDocumentationCommentTo(declaration, property, options); }
private SDProperty GetParsedProperty(IPropertySymbol property) { var sdProperty = new SDProperty(property.GetIdentifier()) { Name = property.Name, DeclaringType = _typeRefParser.GetParsedTypeReference(property.ContainingType), Accessibility = property.DeclaredAccessibility.ToString().ToLower(), ReturnType = _typeRefParser.GetParsedTypeReference(property.Type), CanGet = property.GetMethod != null, CanSet = property.SetMethod != null, IsAbstract = property.IsAbstract, IsVirtual = property.IsVirtual, IsOverride = property.IsOverride, Documentations = DocumentationParser.ParseDocumentation(property) }; ParserOptions.SDRepository.AddMember(sdProperty); return sdProperty; }
private IList<SyntaxNode> GetSetAccessorStatements( Compilation compilation, IPropertySymbol property, bool generateAbstractly, CancellationToken cancellationToken) { if (generateAbstractly) { return null; } var factory = this.Document.GetLanguageService<SyntaxGenerator>(); if (ThroughMember != null) { var throughExpression = CreateThroughExpression(factory); SyntaxNode expression; if (property.IsIndexer) { expression = throughExpression; } else { expression = factory.MemberAccessExpression( throughExpression, factory.IdentifierName(property.Name)); } if (property.Parameters.Length > 0) { var arguments = factory.CreateArguments(property.Parameters.As<IParameterSymbol>()); expression = factory.ElementAccessExpression(expression, arguments); } expression = factory.AssignmentStatement(expression, factory.IdentifierName("value")); return new[] { factory.ExpressionStatement(expression) }; } return factory.CreateThrowNotImplementedStatementBlock(compilation); }
public static MemberDeclarationSyntax GenerateProperty(PropertyDeclarationSyntax property, IPropertySymbol propertySemanticData, List<string> usedNames) { PropertyDeclarationSyntax declaration = SF.PropertyDeclaration(property.Type, property.Identifier.Text) .AddModifiers(property.Modifiers.ToArray()); var block = SF.Block(GetThrowNotImplementedBlockSyntax()); if (property.AccessorList.Accessors.Count > 0) { if (property.AccessorList.Accessors.Any(p => p.Keyword.Text == "get")) { declaration = declaration.AddAccessorListAccessors(SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, block)); } if (property.AccessorList.Accessors.Any(p => p.Keyword.Text == "set")) { declaration = declaration.AddAccessorListAccessors(SF.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, block)); } } return declaration; }
public abstract SyntaxNode CreatePropertyDeclaration(IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options);
private ExternalCodeProperty(CodeModelState state, ProjectId projectId, IPropertySymbol symbol) : base(state, projectId, symbol) { }
internal static async Task TestAddPropertyAsync( string initial, string expected, string name = "P", Accessibility defaultAccessibility = Accessibility.Public, Accessibility setterAccessibility = Accessibility.Public, DeclarationModifiers modifiers = default(DeclarationModifiers), string getStatements = null, string setStatements = null, Type type = null, IPropertySymbol explicitInterfaceSymbol = null, ImmutableArray <Func <SemanticModel, IParameterSymbol> > parameters = default(ImmutableArray <Func <SemanticModel, IParameterSymbol> >), bool isIndexer = false, CodeGenerationOptions codeGenerationOptions = default(CodeGenerationOptions), bool ignoreTrivia = true, IDictionary <OptionKey, object> options = null) { // This assumes that tests will not use place holders for get/set statements at the same time if (getStatements != null) { expected = expected.Replace("$$", getStatements); } if (setStatements != null) { expected = expected.Replace("$$", setStatements); } using (var context = await TestContext.CreateAsync(initial, expected, ignoreTrivia)) { if (options != null) { foreach (var kvp in options) { context.Workspace.Options = context.Workspace.Options.WithChangedOption(kvp.Key, kvp.Value); } } var typeSymbol = GetTypeSymbol(type)(context.SemanticModel); var getParameterSymbols = GetParameterSymbols(parameters, context); var setParameterSymbols = getParameterSymbols == null ? default(ImmutableArray <IParameterSymbol>) : getParameterSymbols.Add(Parameter(type, "value")(context.SemanticModel)); IMethodSymbol getAccessor = CodeGenerationSymbolFactory.CreateMethodSymbol( default(ImmutableArray <AttributeData>), defaultAccessibility, new DeclarationModifiers(isAbstract: getStatements == null), typeSymbol, false, null, "get_" + name, default(ImmutableArray <ITypeParameterSymbol>), getParameterSymbols, statements: context.ParseStatements(getStatements)); IMethodSymbol setAccessor = CodeGenerationSymbolFactory.CreateMethodSymbol( default(ImmutableArray <AttributeData>), setterAccessibility, new DeclarationModifiers(isAbstract: setStatements == null), GetTypeSymbol(typeof(void))(context.SemanticModel), false, null, "set_" + name, default(ImmutableArray <ITypeParameterSymbol>), setParameterSymbols, statements: context.ParseStatements(setStatements)); // If get is provided but set isn't, we don't want an accessor for set if (getStatements != null && setStatements == null) { setAccessor = null; } // If set is provided but get isn't, we don't want an accessor for get if (getStatements == null && setStatements != null) { getAccessor = null; } var property = CodeGenerationSymbolFactory.CreatePropertySymbol( default(ImmutableArray <AttributeData>), defaultAccessibility, modifiers, typeSymbol, false, explicitInterfaceSymbol, name, getParameterSymbols, getAccessor, setAccessor, isIndexer); context.Result = await context.Service.AddPropertyAsync(context.Solution, (INamedTypeSymbol)context.GetDestination(), property, codeGenerationOptions); } }
public static bool IsInstanceLengthCheck( IPropertySymbol lengthLikeProperty, IOperation instance, IOperation operation ) => operation is IPropertyReferenceOperation propertyRef &&
protected void AddDescriptionForProperty(IPropertySymbol symbol) { AddToGroup(SymbolDescriptionGroups.MainDescription, ToMinimalDisplayParts(symbol, s_memberSignatureDisplayFormat)); }
private async Task <TestGenerationContext> CollectTestGenerationContextAsync( ProjectItemSummary selectedFile, string targetProjectNamespace, TestFramework testFramework, MockFramework mockFramework) { Microsoft.CodeAnalysis.Solution solution = CreateUnitTestBoilerplateCommandPackage.VisualStudioWorkspace.CurrentSolution; DocumentId documentId = solution.GetDocumentIdsWithFilePath(selectedFile.FilePath).FirstOrDefault(); if (documentId == null) { throw new InvalidOperationException("Could not find document in solution with file path " + selectedFile.FilePath); } var document = solution.GetDocument(documentId); SyntaxNode root = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); SyntaxNode firstClassDeclaration = root.DescendantNodes().FirstOrDefault(node => node.Kind() == SyntaxKind.ClassDeclaration); if (firstClassDeclaration == null) { throw new InvalidOperationException("Could not find class declaration."); } if (firstClassDeclaration.ChildTokens().Any(node => node.Kind() == SyntaxKind.AbstractKeyword)) { throw new InvalidOperationException("Cannot unit test an abstract class."); } SyntaxToken classIdentifierToken = firstClassDeclaration.ChildTokens().FirstOrDefault(n => n.Kind() == SyntaxKind.IdentifierToken); if (classIdentifierToken == default(SyntaxToken)) { throw new InvalidOperationException("Could not find class identifier."); } NamespaceDeclarationSyntax namespaceDeclarationSyntax = null; if (!TypeUtilities.TryGetParentSyntax(firstClassDeclaration, out namespaceDeclarationSyntax)) { throw new InvalidOperationException("Could not find class namespace."); } // Find property injection types var injectableProperties = new List <InjectableProperty>(); string classFullName = namespaceDeclarationSyntax.Name + "." + classIdentifierToken; INamedTypeSymbol classType = semanticModel.Compilation.GetTypeByMetadataName(classFullName); foreach (ISymbol member in classType.GetBaseTypesAndThis().SelectMany(n => n.GetMembers())) { if (member.Kind == SymbolKind.Property) { IPropertySymbol property = (IPropertySymbol)member; foreach (AttributeData attribute in property.GetAttributes()) { if (PropertyInjectionAttributeNames.Contains(attribute.AttributeClass.ToString())) { var injectableProperty = InjectableProperty.TryCreateInjectableProperty(property.Name, property.Type.ToString(), mockFramework); if (injectableProperty != null) { injectableProperties.Add(injectableProperty); } } } } } string className = classIdentifierToken.ToString(); // Find constructor injection types List <InjectableType> constructorInjectionTypes = new List <InjectableType>(); SyntaxNode constructorDeclaration = firstClassDeclaration.ChildNodes().FirstOrDefault(n => n.Kind() == SyntaxKind.ConstructorDeclaration); if (constructorDeclaration != null) { constructorInjectionTypes.AddRange( GetParameterListNodes(constructorDeclaration) .Select(node => InjectableType.TryCreateInjectableTypeFromParameterNode(node, semanticModel, mockFramework))); } // Find public method declarations IList <MethodDescriptor> methodDeclarations = new List <MethodDescriptor>(); foreach (MethodDeclarationSyntax methodDeclaration in firstClassDeclaration.ChildNodes().Where( n => n.Kind() == SyntaxKind.MethodDeclaration && ((MethodDeclarationSyntax)n).Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)))) { var parameterList = GetParameterListNodes(methodDeclaration).ToList(); var parameterTypes = GetArgumentDescriptors(parameterList, semanticModel, mockFramework); var isAsync = methodDeclaration.Modifiers.Any(m => m.IsKind(SyntaxKind.AsyncKeyword)) || DoesReturnTask(methodDeclaration); var hasReturnType = !DoesReturnNonGenericTask(methodDeclaration) && !DoesReturnVoid(methodDeclaration); methodDeclarations.Add(new MethodDescriptor(methodDeclaration.Identifier.Text, parameterTypes, isAsync, hasReturnType)); } string unitTestNamespace; string relativePath = this.GetRelativePath(selectedFile); if (string.IsNullOrEmpty(relativePath)) { unitTestNamespace = targetProjectNamespace; } else { List <string> defaultNamespaceParts = targetProjectNamespace.Split('.').ToList(); List <string> unitTestNamespaceParts = new List <string>(defaultNamespaceParts); unitTestNamespaceParts.AddRange(relativePath.Split('\\')); unitTestNamespace = string.Join(".", unitTestNamespaceParts); } List <InjectableType> injectedTypes = new List <InjectableType>(injectableProperties); injectedTypes.AddRange(constructorInjectionTypes.Where(t => t != null)); GenerateMockNames(injectedTypes); return(new TestGenerationContext( mockFramework, testFramework, unitTestNamespace, className, namespaceDeclarationSyntax.Name.ToString(), injectableProperties, constructorInjectionTypes, injectedTypes, methodDeclarations)); }
private IList <SymbolDisplayPart> GetPostambleParts(IPropertySymbol indexer) { return(SpecializedCollections.SingletonList( Punctuation(SyntaxKind.CloseBracketToken))); }
private bool IsAssigningIntendedValueToPropertyDerivedFromType(SyntaxNode assignment, SemanticModel model, Func <IPropertySymbol, bool> isTargetPropertyFunc, Func <SyntaxNode, bool> isIntendedValueFunc, out bool isTargetProperty) { bool isIntendedValue; SyntaxNode left = _syntaxNodeHelper.GetAssignmentLeftNode(assignment); SyntaxNode right = _syntaxNodeHelper.GetAssignmentRightNode(assignment); IPropertySymbol leftSymbol = SyntaxNodeHelper.GetCalleePropertySymbol(left, model); isTargetProperty = isTargetPropertyFunc(leftSymbol); if (!isTargetProperty) { return(false); } // call to isIntendedValueFunc must be after checking isTargetProperty // since the logic of isIntendedValueFunc relies on corresponding SyntaxNode isIntendedValue = isIntendedValueFunc(right); // Here's an example that needs some extra check: // // class TestClass : XmlDocument // { // private XmlDocument doc = new XmlDocument(); // public TestClass(XmlDocument doc) // { // this.doc.XmlResolver = null; // } // } // // Even though the assignment would return true for both isTargetPropertyFunc and isIntendedValueFunc, // it is not setting the actual property for this class. // The goal is to find all assignment like in the example above, "this.xxx.xxx.Property = ...;". // For simplicity, here we adopt a simple but inaccurate logic: // If the target is a member access node, then the only pattern we are looking for is "this.Property" SyntaxNode memberAccessNode = _syntaxNodeHelper.GetDescendantMemberAccessExpressionNodes(left).FirstOrDefault(); // if assignment target doesn't have any member access node, // then we treat it as an instance property access without explicit 'this' ('Me' in VB) if (memberAccessNode == null) { //stop here, to avoid false positive, as long as there's one setting <Property> to secure value, we are happy return(isIntendedValue); } SyntaxNode exp = _syntaxNodeHelper.GetMemberAccessExpressionNode(memberAccessNode); ISymbol expSymbol = SyntaxNodeHelper.GetSymbol(exp, model); isTargetProperty = expSymbol.Kind == SymbolKind.Parameter && ((IParameterSymbol)expSymbol).IsThis; if (!isTargetProperty) { return(false); } SyntaxNode name = _syntaxNodeHelper.GetMemberAccessNameNode(memberAccessNode); ISymbol nameSymbol = SyntaxNodeHelper.GetSymbol(name, model); isTargetProperty = isTargetPropertyFunc(nameSymbol as IPropertySymbol); if (!isTargetProperty) { return(false); } // stop here, same reason as stated above return(isIntendedValue); }
private static bool IsAbstractPropertyImplemented(INamedTypeSymbol classOrStructType, IPropertySymbol propertySymbol, CancellationToken cancellationToken) { // A property is only fully implemented if both it's setter and getter is implemented. if (propertySymbol.GetMethod != null) { if (classOrStructType.FindImplementationForAbstractMember(propertySymbol.GetMethod) == null) { return(false); } } if (propertySymbol.SetMethod != null) { if (classOrStructType.FindImplementationForAbstractMember(propertySymbol.SetMethod) == null) { return(false); } } return(true); }
internal static bool TryGetProperty(this ITypeSymbol type, string name, out IPropertySymbol property) { return(type.TryGetSingleMember(name, out property)); }
protected override IEnumerable <Diagnostic> AnalyzeName(IPropertySymbol symbol) => AnalyzeName(symbol);
protected override bool ShallAnalyze(IPropertySymbol symbol) => ShallAnalyze(symbol.Type) && symbol.ContainingType.IsTestClass() is false;
public override SyntaxNode CreatePropertyDeclaration( IPropertySymbol property, CodeGenerationDestination destination, CodeGenerationOptions options) { return(PropertyGenerator.GeneratePropertyDeclaration(property, destination, options)); }
protected abstract bool TryInitializeExplicitInterfaceState(SemanticDocument document, SyntaxNode node, CancellationToken cancellationToken, out SyntaxToken identifierToken, out IPropertySymbol propertySymbol, out INamedTypeSymbol typeToGenerateIn);
public static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context) { var property = (PropertyDeclarationSyntax)context.Node; if (property.ContainsDiagnostics) { return; } SemanticModel semanticModel = context.SemanticModel; CancellationToken cancellationToken = context.CancellationToken; IFieldSymbol fieldSymbol = null; AccessorDeclarationSyntax getter = null; AccessorDeclarationSyntax setter = null; ArrowExpressionClauseSyntax expressionBody = property.ExpressionBody; if (expressionBody != null) { fieldSymbol = GetBackingFieldSymbol(expressionBody, semanticModel, cancellationToken); } else { getter = property.Getter(); if (getter != null) { setter = property.Setter(); if (setter != null) { fieldSymbol = GetBackingFieldSymbol(getter, setter, semanticModel, cancellationToken); } else { fieldSymbol = GetBackingFieldSymbol(getter, semanticModel, cancellationToken); } } } if (fieldSymbol == null) { return; } var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.GetSyntax(cancellationToken); if (variableDeclarator.SyntaxTree != property.SyntaxTree) { return; } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken); if (propertySymbol == null) { return; } if (!propertySymbol.ExplicitInterfaceImplementations.IsDefaultOrEmpty) { return; } if (propertySymbol.IsStatic != fieldSymbol.IsStatic) { return; } if (!propertySymbol.Type.Equals(fieldSymbol.Type)) { return; } if (propertySymbol.ContainingType?.Equals(fieldSymbol.ContainingType) != true) { return; } if (setter == null && propertySymbol.IsOverride && propertySymbol.OverriddenProperty?.SetMethod != null) { return; } if (BackingFieldHasNonSerializedAttribute(fieldSymbol, context.Compilation)) { return; } if (HasStructLayoutAttributeWithExplicitKind(propertySymbol.ContainingType, context.Compilation)) { return; } if (IsBackingFieldUsedInRefOrOutArgument(context, fieldSymbol, property)) { return; } if (!CheckPreprocessorDirectives(property, variableDeclarator)) { return; } context.ReportDiagnostic(DiagnosticDescriptors.UseAutoProperty, property.Identifier); if (property.ExpressionBody != null) { context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, property.ExpressionBody); } else { if (getter != null) { FadeOutBodyOrExpressionBody(context, getter); } if (setter != null) { FadeOutBodyOrExpressionBody(context, setter); } } }
private bool HasAnyMatchingGetOrSetMethods(IPropertySymbol property, string name) { return(HasAnyMatchingGetMethods(property, name) || HasAnyMatchingSetMethods(property, name)); }
public static IPropertySymbol OverrideProperty( this SyntaxGenerator codeFactory, IPropertySymbol overriddenProperty, SymbolModifiers modifiers, INamedTypeSymbol containingType, Document document, CancellationToken cancellationToken) { var getAccessibility = overriddenProperty.GetMethod.ComputeResultantAccessibility(containingType); var setAccessibility = overriddenProperty.SetMethod.ComputeResultantAccessibility(containingType); SyntaxNode getBody = null; SyntaxNode setBody = null; // Implement an abstract property by throwing not implemented in accessors. if (overriddenProperty.IsAbstract) { getBody = codeFactory.CreateThrowNotImplementStatement(document.Project.GetCompilationAsync(cancellationToken).WaitAndGetResult(cancellationToken)); setBody = getBody; } else if (overriddenProperty.IsIndexer() && document.Project.Language == LanguageNames.CSharp) { // Indexer: return or set base[]. Only in C#, since VB must refer to these by name. getBody = codeFactory.ReturnStatement( codeFactory.ElementAccessExpression( codeFactory.BaseExpression(), codeFactory.CreateArguments(overriddenProperty.Parameters))); setBody = codeFactory.ExpressionStatement( codeFactory.AssignmentStatement( codeFactory.ElementAccessExpression( codeFactory.BaseExpression(), codeFactory.CreateArguments(overriddenProperty.Parameters)), codeFactory.IdentifierName("value"))); } else if (overriddenProperty.GetParameters().Any()) { // Call accessors directly if C# overriding VB if (document.Project.Language == LanguageNames.CSharp && SymbolFinder.FindSourceDefinitionAsync(overriddenProperty, document.Project.Solution) .WaitAndGetResult(CancellationToken.None).Language == LanguageNames.VisualBasic) { var getName = overriddenProperty.GetMethod != null ? overriddenProperty.GetMethod.Name : null; var setName = overriddenProperty.SetMethod != null ? overriddenProperty.SetMethod.Name : null; getBody = getName == null ? null : codeFactory.ReturnStatement( codeFactory.InvocationExpression( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(getName)), codeFactory.CreateArguments(overriddenProperty.Parameters))); setBody = setName == null ? null : codeFactory.ExpressionStatement( codeFactory.InvocationExpression( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(setName)), codeFactory.CreateArguments(overriddenProperty.SetMethod.GetParameters()))); } else { getBody = codeFactory.ReturnStatement( codeFactory.InvocationExpression( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(overriddenProperty.Name)), codeFactory.CreateArguments(overriddenProperty.Parameters))); setBody = codeFactory.ExpressionStatement( codeFactory.AssignmentStatement( codeFactory.InvocationExpression( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(overriddenProperty.Name)), codeFactory.CreateArguments(overriddenProperty.Parameters)), codeFactory.IdentifierName("value"))); } } else { // Regular property: return or set the base property getBody = codeFactory.ReturnStatement( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(overriddenProperty.Name))); setBody = codeFactory.ExpressionStatement( codeFactory.AssignmentStatement( codeFactory.MemberAccessExpression( codeFactory.BaseExpression(), codeFactory.IdentifierName(overriddenProperty.Name)), codeFactory.IdentifierName("value"))); } // Only generate a getter if the base getter is accessible. IMethodSymbol accessorGet = null; if (overriddenProperty.GetMethod != null && overriddenProperty.GetMethod.IsAccessibleWithin(containingType)) { accessorGet = CodeGenerationSymbolFactory.CreateMethodSymbol( overriddenProperty.GetMethod, accessibility: getAccessibility, statements: new[] { getBody }, modifiers: modifiers); } // Only generate a setter if the base setter is accessible. IMethodSymbol accessorSet = null; if (overriddenProperty.SetMethod != null && overriddenProperty.SetMethod.IsAccessibleWithin(containingType) && overriddenProperty.SetMethod.DeclaredAccessibility != Accessibility.Private) { accessorSet = CodeGenerationSymbolFactory.CreateMethodSymbol( overriddenProperty.SetMethod, accessibility: setAccessibility, statements: new[] { setBody }, modifiers: modifiers); } return(CodeGenerationSymbolFactory.CreatePropertySymbol( overriddenProperty, accessibility: overriddenProperty.ComputeResultantAccessibility(containingType), modifiers: modifiers, name: overriddenProperty.Name, isIndexer: overriddenProperty.IsIndexer(), getMethod: accessorGet, setMethod: accessorSet)); }
public PropertyDescription(uint fieldId, IPropertySymbol property) { this.FieldId = fieldId; this.Property = property; }
private static bool HasPublicSetter(IPropertySymbol propertySymbol) => propertySymbol.SetMethod != null && !privateOrInternalAccessibility.Contains(propertySymbol.GetEffectiveAccessibility()) && !privateOrInternalAccessibility.Contains(propertySymbol.SetMethod.DeclaredAccessibility);
protected abstract bool ImplementsExplicitGetterOrSetter(IPropertySymbol property);
private static int CompareProperties(IPropertySymbol xProperty, string[] xTypeNames, IPropertySymbol yProperty, string[] yTypeNames) { return(CompareParameters(xProperty.Parameters, xTypeNames, yProperty.Parameters, yTypeNames)); }
protected abstract IEnumerable <FieldData> FindFieldReads(IPropertySymbol property, Compilation compilation);
public static PropertyValidationResult GetPropertyRetrieverArgumentStatus( ArgumentSyntax propertyRetrieverArgument, SyntaxNodeAnalysisContext context, ITypeSymbol propertyValueTypeIfKnown, bool allowReadOnlyProperties, out IPropertySymbol propertyIfSuccessfullyRetrieved) { if (propertyRetrieverArgument == null) { throw new ArgumentNullException(nameof(propertyRetrieverArgument)); } // Most of the validation here ensures that an argument is passed is an explicit property getter lamba (eg. "_ => _.Name") but there // are times where it would be helpful to be able to share a lambda reference (or pass one into a method that will then pass it to a // With call) and so we don't want to ONLY support the explicit lambda formats. To enable that, there is a PropertyIdentifier<T, TProp> // class that may be cast to a Func<T, TProp> which means that the lambda validation need not apply (note that the lambda validation // WILL be applied to the PropertyIdentifier<T, TProp> initialisations, so validation may not be bypassed in this manner - it's just // moved around a bit) // - Note: We don't have to worry about propertyValueTypeIfKnown here because the validation around ensuring that we don't use too // loose of a type will have been done when the PropertyIdentifier<T, TPropertyValue> was initialised if (IsPropertyIdentifierReference(propertyRetrieverArgument.Expression, context)) { propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.Ok); } // An alternative to generating and passing round PropertyIdentifier<T, TPropertyValue> references is to mark method arguments that are // of the the appropriate lambda forms with the [PropertyIdentifier] attribute - then the parameter may be passed into a With or CtorSet // method (since there will have been validation elsewhere to ensure that the argument passed to [PropertyIdentifier] parameter meets // the criteria checked for below) // - Note: We don't have to worry about propertyValueTypeIfKnown for the same reason as we don't above; the validation will have been // applied at the point at which the [PropertyIdentifier] argument was provided bool isNotPropertyIdentifierButIsMethodParameterOfDelegateType; if (IsPropertyIdentifierArgument(propertyRetrieverArgument.Expression, context, out isNotPropertyIdentifierButIsMethodParameterOfDelegateType)) { propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.Ok); } else if (isNotPropertyIdentifierButIsMethodParameterOfDelegateType) { // If it the property identifier is a method argument value and it's a delegate but it doesn't have the [PropertyIdentifier] attribute // on it then it seems likely that the user has just forgotten it (or is not aware of it) so, instead of showing the more generic // NotSimpleLambdaExpression warning, allow the analyser to show a more helpful message. propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.MethodParameterWithoutPropertyIdentifierAttribute); } SimpleNameSyntax targetNameIfSimpleLambdaExpression; if (propertyRetrieverArgument.Expression.Kind() != SyntaxKind.SimpleLambdaExpression) { propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.NotSimpleLambdaExpression); } else { var propertyRetrieverExpression = (SimpleLambdaExpressionSyntax)propertyRetrieverArgument.Expression; if (propertyRetrieverExpression.Body.Kind() != SyntaxKind.SimpleMemberAccessExpression) { propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.NotSimpleLambdaExpression); } var memberAccess = (MemberAccessExpressionSyntax)propertyRetrieverExpression.Body; if (memberAccess.Expression.Kind() != SyntaxKind.IdentifierName) { // The lambda must be of the form "_ => _.Name" and not "_ => ((ISomething)_).Name" or anything like that. This ensures // that all public gettable properties on the type can be checked for a setter while also allowing it to implement other // interfaces which don't follow these rules, so long as those interfaces are explicitly implemented. If it was acceptable // to cast the lambda target then this would not be possible. propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.IndirectTargetAccess); } targetNameIfSimpleLambdaExpression = ((MemberAccessExpressionSyntax)propertyRetrieverExpression.Body).Name; } var target = context.SemanticModel.GetSymbolInfo(targetNameIfSimpleLambdaExpression).Symbol; if (target == null) { // We won't be able to retrieve a Symbol "if the given expression did not bind successfully to a single symbol" - this means // that the code is not in a complete state. We can only identify errors when everything is properly written and consistent. { propertyIfSuccessfullyRetrieved = null; return(PropertyValidationResult.UnableToConfirmOrDeny); } } propertyIfSuccessfullyRetrieved = target as IPropertySymbol; if (propertyIfSuccessfullyRetrieved == null) { return(PropertyValidationResult.LambdaDoesNotTargetProperty); } if (propertyIfSuccessfullyRetrieved.GetMethod == null) { return(PropertyValidationResult.MissingGetter); } if (HasDisallowedAttribute(propertyIfSuccessfullyRetrieved.GetMethod)) { return(PropertyValidationResult.GetterHasBridgeAttributes); } var hasReadOnlyAttribute = propertyIfSuccessfullyRetrieved.GetAttributes().Any( a => a.AttributeClass.ToString() == AnalyserAssemblyName + ".ReadOnlyAttribute" ); if (!allowReadOnlyProperties && hasReadOnlyAttribute) { return(PropertyValidationResult.IsReadOnly); } // Note about looking for a setter: Previously, it was required that a property have a getter AND a setter, though it was fine for // that setter to be private (in fact, it SHOULD be private if the containing class is not to have modifiable instances). This check // had to be relaxed for properties in classes in referenced assemblies since the meta data for the external assembly would not declare // the presence of a private setter. Now that (as of September 2016) Bridge supports C# 6 syntax, we also have to deal with the case // where a setter may not be present in classes that we have access to the source code for at this point. We COULD do extra work to // try to ensure that this only happens if the getter has no body (meaning that it must be a readonly auto-property, if it has a // getter with no body and has no setter) but I think that it makes more sense to just skip the check altogether - it's skipped for // referenced assemblies because the assumption is that the IAmImmutable analyser would pick up any invalid classes in the project // project in which those classes were written, so we can do the same here (yes, someone could bypass that by disabling the analyser // or using Visual Studio pre-2015 or one of any number of other means) but there are lots of ways to get around the type system if // you're creative when considering a Bridge project since JavaScript is so malleable (so it doesn't seem worth going mad trying to // make it impossible to circumvent, it's fine just to make it so that there's clearly some shenanigans going on and that everything // will work if there isn't). if ((propertyIfSuccessfullyRetrieved.SetMethod != null) && HasDisallowedAttribute(propertyIfSuccessfullyRetrieved.SetMethod)) { return(PropertyValidationResult.SetterHasBridgeAttributes); } // Ensure that the property value is at least as specific a type as the target property. For example, if the target property is of // type string and we know that the value that the code wants to set that property to be is an object then we need to nip that in // the bud. This is, unfortunately, quite an easy situation to fall into - if, for example, "x" is an instance of an IAmImmutable- // implementing class that has a "Name" property that is a string then the following will compile // // x = x.With(_ => _.Name, new object()); // // Although the lambda "_ => _.Name" is a Func<Whatever, string> it may also be interpreted as a Func<Whatever, object> if the // "TPropertyValue" generic type argument of the With<T, TPropertyValue> is inferred (or explicitly specified) as object. if ((propertyValueTypeIfKnown != null) && !(propertyValueTypeIfKnown is IErrorTypeSymbol)) { if (!IsEqualToOrInheritsFrom(propertyValueTypeIfKnown, propertyIfSuccessfullyRetrieved.GetMethod.ReturnType)) { return(PropertyValidationResult.PropertyIsOfMoreSpecificTypeThanSpecificValueType); } } return(PropertyValidationResult.Ok); }
protected bool IsAutoProperty(IPropertySymbol property) { return(IsAutoProperty(property, out _)); }
protected abstract void BuildPropertyDeclaration(IPropertySymbol propertySymbol, _VSOBJDESCOPTIONS options);
public static ExpressionSyntax CreateNewExpression(SyntaxNode node, SyntaxToken identifier, IPropertySymbol propertySymbol) { if (node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression) && ((MemberAccessExpressionSyntax)node.Parent).Name == node) { return(IdentifierName(identifier)); } else if (propertySymbol.IsStatic) { return(ParseName($"{propertySymbol.ContainingType.ToTypeSyntax()}.{propertySymbol.ToDisplayString(_symbolDisplayFormat)}") .WithSimplifierAnnotation()); } else { return(IdentifierName(identifier).QualifyWithThis()); } }
internal static EnvDTE.CodeProperty Create(CodeModelState state, ProjectId projectId, IPropertySymbol symbol) { var element = new ExternalCodeProperty(state, projectId, symbol); return((EnvDTE.CodeProperty)ComAggregate.CreateAggregatedObject(element)); }
public static async Task <Solution> RefactorAsync( Document document, PropertyDeclarationSyntax propertyDeclaration, CancellationToken cancellationToken) { SyntaxToken propertyIdentifier = propertyDeclaration.Identifier.WithoutTrivia(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, cancellationToken); ISymbol fieldSymbol = GetFieldSymbol(propertyDeclaration, semanticModel, cancellationToken); var variableDeclarator = (VariableDeclaratorSyntax)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; var fieldDeclaration = (FieldDeclarationSyntax)variableDeclaration.Parent; bool isSingleDeclarator = variableDeclaration.Variables.Count == 1; Solution solution = document.Solution(); foreach (DocumentReferenceInfo info in await SyntaxFinder.FindReferencesByDocumentAsync(fieldSymbol, solution, allowCandidate: false, cancellationToken: cancellationToken).ConfigureAwait(false)) { ImmutableArray <SyntaxNode> nodes = info.References; if (propertyDeclaration.SyntaxTree == info.SyntaxTree) { nodes = nodes.Add(propertyDeclaration); if (isSingleDeclarator) { nodes = nodes.Add(fieldDeclaration); } else { nodes = nodes.Add(variableDeclarator); } } SyntaxNode newRoot = info.Root.ReplaceNodes(nodes, (node, _) => { switch (node.Kind()) { case SyntaxKind.IdentifierName: { return(CreateNewExpression(node, propertyIdentifier, propertySymbol) .WithTriviaFrom(node) .WithFormatterAnnotation()); } case SyntaxKind.PropertyDeclaration: { return(CreateAutoProperty(propertyDeclaration, variableDeclarator.Initializer)); } case SyntaxKind.VariableDeclarator: case SyntaxKind.FieldDeclaration: { return(node.WithAdditionalAnnotations(_removeAnnotation)); } default: { Debug.Fail(node.ToString()); return(node); } } }); SyntaxNode nodeToRemove = newRoot.GetAnnotatedNodes(_removeAnnotation).FirstOrDefault(); if (nodeToRemove != null) { newRoot = newRoot.RemoveNode(nodeToRemove, SyntaxRemoveOptions.KeepUnbalancedDirectives); } solution = solution.WithDocumentSyntaxRoot(info.Document.Id, newRoot); } return(solution); }
public static bool?AreAutoPropertiesMinimized(this IPropertySymbol property) { return(property.GetAttributeValue <bool?>(Context.Instance.JsAttributeType, "AreAutoPropertiesMinimized", null)); }
protected override TDeclarationNode AddProperty <TDeclarationNode>(TDeclarationNode destination, IPropertySymbol property, CodeGenerationOptions options, IList <bool> availableIndices) { CheckDeclarationNode <TypeDeclarationSyntax, CompilationUnitSyntax>(destination); // Can't generate a property with parameters. So generate the setter/getter individually. if (!PropertyGenerator.CanBeGenerated(property)) { var members = new List <ISymbol>(); if (property.GetMethod != null) { var getMethod = property.GetMethod; if (property is CodeGenerationSymbol) { foreach (var annotation in ((CodeGenerationSymbol)property).GetAnnotations()) { getMethod = annotation.AddAnnotationToSymbol(getMethod); } } members.Add(getMethod); } if (property.SetMethod != null) { var setMethod = property.SetMethod; if (property is CodeGenerationSymbol) { foreach (var annotation in ((CodeGenerationSymbol)property).GetAnnotations()) { setMethod = annotation.AddAnnotationToSymbol(setMethod); } } members.Add(setMethod); } if (members.Count > 1) { options = CreateOptionsForMultipleMembers(options); } return(AddMembers(destination, members, availableIndices, options)); } if (destination is TypeDeclarationSyntax) { return(Cast <TDeclarationNode>(PropertyGenerator.AddPropertyTo(Cast <TypeDeclarationSyntax>(destination), property, options, availableIndices))); } else { return(Cast <TDeclarationNode>(PropertyGenerator.AddPropertyTo(Cast <CompilationUnitSyntax>(destination), property, options, availableIndices))); } }