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); }
public TraitLocationAttribute(CommonLocation common) : this(TraitLocations.PathOf(common)) { }
public static string PathOf(CommonLocation common) { return(Names[(int)common]); }
static CommonSyntaxNode GetNode(IDocument doc, CommonLocation loc) { return(loc.SourceTree.GetRoot().FindToken(loc.SourceSpan.Start).Parent.Parent.Parent); }
/// 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); }
public T RequiresComponent <T>(CommonLocation commonLocation) where T : Component { return(RequiresComponent <T>(TraitLocations.PathOf(commonLocation))); }