public Issue(
            ErrorCode errorCode,
            CommonSyntaxNode syntaxNode,
            ISymbol symbol)
        {
            #region Input validtion

            if (!Enum.IsDefined(typeof(ErrorCode), errorCode))
            {
                throw new ArgumentException("errorCode is not defined.", "errorCode");
            }

            if (syntaxNode == null)
            {
                throw new ArgumentNullException("syntaxNode");
            }

            if (symbol == null)
            {
                throw new ArgumentNullException("symbol");
            }

            #endregion

            _errorCode = errorCode;
            _description = DescriptionResolver.GetDescription(errorCode);
            _syntaxNode = syntaxNode;
            _symbol = symbol;
            _location = syntaxNode.GetLocation();

            _sourceLineNumber = GetSourceLineNumber();
            _sourceLineText = GetSourceLineText(_sourceLineNumber);
            _sourceFileName = GetSourceFileName();
        }
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            SyntaxNode     root  = (SyntaxNode)document.GetSyntaxRoot(cancellationToken);
            ISemanticModel model = document.GetSemanticModel(cancellationToken);

            SyntaxToken token = root.FindToken(textSpan.Start, findInsideTrivia: true);

            // Verify is the selected token an identifier within field declaration
            if (token.Kind == SyntaxKind.IdentifierToken && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End)
            {
                SyntaxNode parentNode = token.Parent;

                if (parentNode == null)
                {
                    return(null);
                }

                FieldDeclarationSyntax fieldDeclaration = parentNode.FirstAncestorOrSelf <FieldDeclarationSyntax>();
                if (fieldDeclaration == null)
                {
                    return(null);
                }

                // If the FieldDeclaration has some errors, then no refactoring should take place
                if (fieldDeclaration.HasDiagnostics)
                {
                    return(null);
                }

                // Get the container that the field belongs to
                TypeDeclarationSyntax containingType = fieldDeclaration.FirstAncestorOrSelf <TypeDeclarationSyntax>();
                if (containingType == null)
                {
                    return(null);
                }

                // Obtain TypeSymbol for class declaration
                ITypeSymbol containingTypeSymbol = model.GetDeclaredSymbol(containingType, cancellationToken) as ITypeSymbol;
                if (containingTypeSymbol == null)
                {
                    return(null);
                }

                // Check is there a base class that the field can be moved to
                INamedTypeSymbol baseTypeSymbol = containingTypeSymbol.BaseType;
                if (baseTypeSymbol == null)
                {
                    return(null);
                }

                // Check is the class defined in source, so that it can be extended
                CommonLocation baseTypeLocation = baseTypeSymbol.Locations.First();
                if (baseTypeLocation != null && baseTypeLocation.IsInSource)
                {
                    int position = baseTypeLocation.SourceSpan.Start;
                    BaseTypeDeclarationSyntax baseTypeDeclaration = baseTypeLocation.SourceTree.GetRoot().FindToken(position).Parent.FirstAncestorOrSelf <BaseTypeDeclarationSyntax>();
                    if (baseTypeDeclaration == null)
                    {
                        return(null);
                    }

                    return(new CodeRefactoring(
                               new[] { new PullUpFieldAction(document, fieldDeclaration, containingType, baseTypeDeclaration) }
                               , fieldDeclaration.Span));
                }
            }

            return(null);
        }
示例#3
0
 public TraitLocationAttribute(CommonLocation common) : this(TraitLocations.PathOf(common))
 {
 }
示例#4
0
 public static string PathOf(CommonLocation common)
 {
     return(Names[(int)common]);
 }
示例#5
0
 static CommonSyntaxNode GetNode(IDocument doc, CommonLocation loc)
 {
     return(loc.SourceTree.GetRoot().FindToken(loc.SourceSpan.Start).Parent.Parent.Parent);
 }
示例#6
0
        /// TODO:
        /// - truly process $if$ $then$'s
        /// - framework version should come from target solution

        public override void CopyAndProcess(string copyToPath, ICodeTemplateParameters parameters, bool overwriteExisting = true, List <string> skip = null)
        {
            var templateFile = VSConfigProvider.Decompress(this.ZippedTemplate, copyToPath, overwriteExisting, skip);

            File.Delete(templateFile);

            this.parameters = parameters;

            foreach (var project in this.Projects)
            {
                if (project.ReplaceParameters)
                {
                    var fileName = Path.Combine(copyToPath, project.FileName);

                    using (var stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite))
                    {
                        ReplaceParameters(stream, parameters);
                    }
                }

                foreach (var projectItem in project.ProjectItems)
                {
                    var fileName    = Path.Combine(copyToPath, projectItem.FileName);
                    var oldFileName = fileName;
                    var fileInfo    = new FileInfo(fileName);

                    if (!fileInfo.Exists)
                    {
                        fileInfo = CommonLocation.GetFiles().Where(f => f.Name == fileInfo.Name).Single();
                        fileName = fileInfo.FullName;
                    }

                    if (!string.IsNullOrEmpty(projectItem.TargetFileName))
                    {
                        var path           = Path.Combine(projectItem.Folder, projectItem.TargetFileName);
                        var targetFileName = Path.Combine(copyToPath, path);
                        var targetFileInfo = new FileInfo(targetFileName);

                        if (fileName != targetFileName)
                        {
                            if (!targetFileInfo.Directory.Exists)
                            {
                                targetFileInfo.Directory.Create();
                            }

                            if (overwriteExisting)
                            {
                                if (targetFileInfo.Exists)
                                {
                                    if (targetFileInfo.IsReadOnly)
                                    {
                                        targetFileInfo.MakeWritable();
                                    }

                                    targetFileInfo.Delete();
                                }
                            }

                            File.Copy(fileName, targetFileName);

                            fileName = targetFileName;
                        }
                    }
                    else if (oldFileName != fileName)
                    {
                        File.Copy(oldFileName, fileName);
                    }

                    if (projectItem.ReplaceParameters)
                    {
                        if (skip == null || !skip.Any(s => s.ToLower() == projectItem.FileName.ToLower()))
                        {
                            fileInfo = new FileInfo(fileName);

                            fileInfo.MakeWritable();

                            using (var stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite))
                            {
                                ReplaceParameters(stream, parameters);
                            }
                        }
                    }
                }
            }
        }
        public CodeRefactoring GetRefactoring(IDocument document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            SyntaxNode  root  = (SyntaxNode)document.GetSyntaxRoot(cancellationToken);
            SyntaxToken token = root.FindToken(textSpan.Start, findInsideTrivia: true);

            SyntaxNode parentNode = token.Parent;

            if (parentNode == null)
            {
                return(null);
            }

            // Verify is the selected token an identifier of a method
            if (token.Kind == SyntaxKind.IdentifierToken && parentNode.Kind == SyntaxKind.IdentifierName && token.Span.Start <= textSpan.End && textSpan.End <= token.Span.End)
            {
                IdentifierNameSyntax identifier = (IdentifierNameSyntax)parentNode;

                InvocationExpressionSyntax invocationExpression = identifier.FirstAncestorOrSelf <InvocationExpressionSyntax>();
                if (invocationExpression == null || invocationExpression.HasDiagnostics)
                {
                    return(null);
                }

                ISemanticModel model = document.GetSemanticModel(cancellationToken);

                ISymbol methodSymbol = model.GetSymbolInfo(invocationExpression.Expression, cancellationToken).Symbol;
                if (methodSymbol == null)
                {
                    return(null);
                }

                // Check is the method defined in source, so that its body can be read and inlined
                CommonLocation methodDeclarationLocation = methodSymbol.Locations.First();
                if (methodDeclarationLocation == null || !methodDeclarationLocation.IsInSource)
                {
                    return(null);
                }

                // Get method declaration based on location
                int position = methodDeclarationLocation.SourceSpan.Start;
                MethodDeclarationSyntax methodDeclaration = methodDeclarationLocation.SourceTree.GetRoot().FindToken(position).Parent.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (methodDeclaration == null)
                {
                    return(null);
                }

                BlockSyntax methodBody = methodDeclaration.Body;

                // Method can be inlined only if it has only one statement, which is return statement
                if (methodBody.Statements.Count != 1 || methodBody.Statements[0].Kind != SyntaxKind.ReturnStatement)
                {
                    return(null);
                }

                ReturnStatementSyntax returnStatement = (ReturnStatementSyntax)methodBody.Statements[0];
                if (returnStatement == null || returnStatement.Expression == null)
                {
                    return(null);
                }

                // If inlined method's invocation expression is the only expression in statement (so its direct parent is ExpressionStatement)
                // then the expression in ReturnStatement should be one of: invocation, object creation, increment, decrement, assignment (or complex assignment).
                if (invocationExpression.Parent != null && invocationExpression.Parent.Kind == SyntaxKind.ExpressionStatement)
                {
                    if (!IsIndependentExpression(returnStatement.Expression))
                    {
                        return(null);
                    }
                }

                // If method is polymorphic, then it should not be inlined. Late binding does not take place.
                MethodSymbol declaredMethodSymbol = (MethodSymbol)model.GetDeclaredSymbol(methodDeclaration);
                if (declaredMethodSymbol.OverriddenMethod != null ||
                    declaredMethodSymbol.MethodKind == MethodKind.ExplicitInterfaceImplementation ||
                    declaredMethodSymbol.IsVirtual ||
                    declaredMethodSymbol.IsOverride)
                {
                    return(null);
                }

                var analysis = model.AnalyzeStatementDataFlow(returnStatement);

                // If parameter is assigned value, it must be either `out' or `ref' to preserve semantics when method is inlined
                // That is, if parameter is modified, the change is reflected before inlining and after inlining

                foreach (var parameter in methodDeclaration.ParameterList.Parameters)
                {
                    ISymbol parameterSymbol = model.GetDeclaredSymbol(parameter, cancellationToken);

                    // Check is the parameter changed in method's body
                    if (analysis.WrittenInside.Contains(parameterSymbol))
                    {
                        // Verify if the modified parameter defined with either `ref' or `out' keyword
                        if (!parameter.Modifiers.Any(n => n.Kind == SyntaxKind.OutKeyword || n.Kind == SyntaxKind.RefKeyword))
                        {
                            return(null);
                        }
                    }
                }

                return(new CodeRefactoring(
                           new[] { new InlineMethodAction(document, invocationExpression, methodDeclaration, returnStatement.Expression) }
                           , invocationExpression.Span));
            }

            return(null);
        }
        /// <summary>
        /// For each given directive return a bound PE reference, or null if the binding fails.
        /// </summary>
        private PortableExecutableReference ResolveReferenceDirective(string reference, CommonLocation location, TCompilation compilation)
        {
            var    tree     = location.SourceTree;
            string basePath = (tree != null && tree.FilePath.Length > 0) ? tree.FilePath : null;

            string fullPath = compilation.FileResolver.ResolveMetadataReference(reference, basePath);

            if (fullPath == null)
            {
                return(null);
            }

            return(compilation.MetadataFileProvider.GetReference(fullPath));
        }
        // Returns null if an assembly of an equivalent identity has not been added previously, otherwise returns the reference that added it.
        // - Both assembly names are strong (have keys) and are either equal or FX unified
        // - Both assembly names are weak (no keys) and have the same simple name.
        private MetadataReference TryAddAssembly(AssemblyIdentity identity, MetadataReference boundReference, DiagnosticBag diagnostics, CommonLocation location,
                                                 ref Dictionary <string, List <ReferencedAssemblyIdentity> > referencesBySimpleName)
        {
            if (referencesBySimpleName == null)
            {
                referencesBySimpleName = new Dictionary <string, List <ReferencedAssemblyIdentity> >(StringComparer.OrdinalIgnoreCase);
            }

            List <ReferencedAssemblyIdentity> sameSimpleNameIdentities;
            string simpleName = identity.Name;

            if (!referencesBySimpleName.TryGetValue(simpleName, out sameSimpleNameIdentities))
            {
                referencesBySimpleName.Add(simpleName, new List <ReferencedAssemblyIdentity> {
                    new ReferencedAssemblyIdentity(identity, boundReference)
                });
                return(null);
            }

            ReferencedAssemblyIdentity equivalent = default(ReferencedAssemblyIdentity);

            if (identity.IsStrongName)
            {
                foreach (var other in sameSimpleNameIdentities)
                {
                    // only compare strong with strong (weak is never equivalent to strong and vice versa)
                    if (other.Identity.IsStrongName && identity.IsEquivalent(other.Identity))
                    {
                        equivalent = other;
                        break;
                    }
                }
            }
            else
            {
                foreach (var other in sameSimpleNameIdentities)
                {
                    // only compare weak with weak
                    if (!other.Identity.IsStrongName && WeakIdentityPropertiesEquivalent(identity, other.Identity))
                    {
                        equivalent = other;
                        break;
                    }
                }
            }

            if (equivalent.Identity == null)
            {
                sameSimpleNameIdentities.Add(new ReferencedAssemblyIdentity(identity, boundReference));
                return(null);
            }

            // equivalent found - ignore and/or report an error:

            if (identity.IsStrongName)
            {
                Debug.Assert(equivalent.Identity.IsStrongName);

                // versions migth have been unified for a Framework assembly:
                if (identity != equivalent.Identity)
                {
                    // Dev11 C# reports an error
                    // Dev11 VB keeps both references in the compilation and reports an ambiguity error when a symbol is used.
                    // BREAKING CHANGE in VB: we report an error for both languages

                    // Multiple assemblies with equivalent identity have been imported: '{0}' and '{1}'. Remove one of the duplicate references.
                    MessageProvider.ReportDuplicateMetadataReferenceStrong(diagnostics, location, boundReference, identity, equivalent.MetadataReference, equivalent.Identity);
                }

                // If the versions match exactly we ignore duplicates w/o reporting errors while
                // Dev11 C# reports:
                //   error CS1703: An assembly with the same identity '{0}' has already been imported. Try removing one of the duplicate references.
                // Dev11 VB reports:
                //   Fatal error BC2000 : compiler initialization failed unexpectedly: Project already has a reference to assembly System.
                //   A second reference to 'D:\Temp\System.dll' cannot be added.
            }
            else
            {
                MessageProvider.ReportDuplicateMetadataReferenceWeak(diagnostics, location, boundReference, identity, equivalent.MetadataReference, equivalent.Identity);
            }

            Debug.Assert(equivalent.MetadataReference != null);
            return(equivalent.MetadataReference);
        }
示例#10
0
 public T RequiresComponent <T>(CommonLocation commonLocation) where T : Component
 {
     return(RequiresComponent <T>(TraitLocations.PathOf(commonLocation)));
 }