16

背景

我正在从事一个小型编码项目,该项目将出售给其他公司。我需要为它创建一些文档,所以我决定使用 Sandcastle。在花了很长时间下载和安装之后,我终于让它工作了,并注意到任何没有评论的公共方法或类都有红色文本说明评论丢失。然后我安装了 Ghostdoc 来帮助加快我的评论速度。这打开了缺少 xml 注释的编译器警告,这很棒,因为我现在有一个我需要注释的所有内容的列表。

问题

我的一个代码文件是一个自动生成的文件,其中包含大约 3000 个编译器警告。我需要能够跳过该文件来创建任何“缺少 Xml 注释”编译器警告。我从这篇文章中知道了这些事情:

  • 我知道我可以关闭项目的编译器警告,但是项目中还有其他文件应该有编译器警告。
  • 我知道我可以#pragma warning disable 1591用来删除编译器警告,但是文件是自动生成的,我真的不想每次都手动重新添加它。
  • 我知道我可以添加一个空注释,但是我真的不想每次重新生成文件时都必须重新添加它。
  • 我可以将文件拉出到它自己的项目中,因为它是其名称空间中的唯一类,然后删除 XML 注释要求,但我不希望客户必须处理另一个 dll。
  • 这些类是部分类,所以我正在考虑尝试找到一种方法来在部分类中添加#pragma 警告禁用,但即使有可能,仍然存在会引发警告的枚举。

如何告诉 VS 忽略特定类型警告的单个文件?

4

3 回答 3

3

我想到了几种可能性:

  1. 你能有另一个类来导入自动生成的 .cs 文件吗?包装类具有编译指示,只导入自动生成的类。
  2. 编写一个 perl 脚本(或简单的 C# 程序),在生成文件之后和编译 .cs 文件之前调用它作为构建事件。
于 2012-07-12T03:34:59.563 回答
3

如果生成的类不应该对您的用户可见,您可以检查生成工具是否具有将类生成为内部而不是公共的选项。

如果您生成的代码是一个 Web 服务引用,您可以在创建引用时指定它(在“添加服务引用”对话框中,高级 -> 生成类的访问级别)。

否则,您可以尝试找到一种方法来自动将生成代码中类型的访问级别从公共更改为内部。

于 2012-07-12T07:00:29.313 回答
1

编辑:我的解决方案

我使用了 David Thielen 的建议并创建了一个 C# 程序,将#pragma warning disable消息插入到我的自动生成的文件中。理想情况下,我将其称为生成文件本身的后期操作,但现在预编译命令就足够了,因为我的语句将是文件中的第一行之一,它只需要读取几行行,看到 disable 语句已经存在,然后退出,所以它不应该减慢构建速度。以下是我的节目,供大家欣赏!:)

/// <summary>
/// Addes #pragma warning disable messages to source code as part of a prebuild to ignore warnings.
/// Primarly used for autogenerated classes that may contain some compiler warnings by default
/// </summary>
public class Program
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="args">
    /// [0] - file to edit
    /// [1] - line number to insert / edit warning disable at
    /// [2+] - warnings numbers to disable</param>
    static void Main(string[] args)
    {
        // Preconditions
        if (args.Length < 2)
        {
            throw new ArgumentException(String.Format("Unexpected number of parameters.{0}Parameters should be [0] - file to edit{0}[1] - line number to insert / edit warning disable at{0}[2+] - warnings numbers to disable", Environment.NewLine));
        }
        else if (args.Length == 2) { return; }

        // Valid number of args, validate arguments
        string filePath = args[0];
        long lineNumber;

        if(!long.TryParse(args[1], out lineNumber)){
            throw new InvalidCastException("Unable to cast \"" + args[1] + "\" to a long");
        }

        string[] compilerWarningNumbers = new string[args.Length - 2];
        Array.ConstrainedCopy(args, 2, compilerWarningNumbers, 0, compilerWarningNumbers.Length);

        // File Name and line number are valid, perform search and replace
        AddOrUpdateCompilerWarningDisabler(filePath, lineNumber, String.Join(",", compilerWarningNumbers));

    }

    private const string TEMP_FILE_POSTFIX = ".CompilerWarningDisabler.txt";
    public static void AddOrUpdateCompilerWarningDisabler(string filePath, long lineNumber, string compilerWarningNumberCSV)
    {
        if (!File.Exists(filePath))
        {
            throw new FileNotFoundException("File path not found!", filePath);
        }

        // Set Clear Readonly Flag
        FileInfo fileInfo = new FileInfo(filePath);
        bool isReadOnly = fileInfo.IsReadOnly;

        // Get Temp File Name and Delete if it already exists
        string tempFile = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + TEMP_FILE_POSTFIX);
        File.Delete(tempFile);

        // Read from the target file and write to a new file.
        int currentLine = 1;
        string line;
        string textToWrite = "#pragma warning disable " + compilerWarningNumberCSV;
        try
        {
            using (StreamReader reader = new StreamReader(filePath))
            using (StreamWriter writer = new StreamWriter(tempFile))
            {
                while ((line = reader.ReadLine()) != null)
                {
                    if (currentLine == lineNumber)
                    {
                        if (line.StartsWith("#pragma warning disable"))
                        {
                            if (line == textToWrite)
                            {
                                // Nothing has changed, don't bother copying file
                                return;
                            }
                            else
                            {
                                line = textToWrite;
                            }
                        }
                        else
                        {
                            writer.WriteLine(textToWrite);
                            writer.WriteLine(line);
                        }
                    }
                    else
                    {
                        writer.WriteLine(line);
                    }
                    currentLine++;
                }

                if (currentLine == lineNumber)
                {
                    writer.WriteLine(textToWrite);
                }

                if (currentLine < lineNumber)
                {
                    throw new InvalidDataException("File " + filePath + " does not contain line number " + lineNumber);
                }
            }

            // This could potentially delete the source file, but this should be messing with autogenerated files, so even if it does happen, it shouldn't be to hard to get it back
            if (isReadOnly)
            {
                fileInfo.IsReadOnly = false;
            }
            File.Delete(filePath);
            File.Move(tempFile, filePath);
            if (isReadOnly)
            {
                new FileInfo(filePath).IsReadOnly = true;
            }
        }
        finally
        {
            File.Delete(tempFile);
        }
    }
}
于 2012-11-05T18:38:29.287 回答