Beispiel #1
0
        internal FileItem(CommentTaskProvider provider, string fileName)
        {
            // Note: The caller should check FileUtility.IsValidPath(fileName) before invoking this constructor.
            this.provider                   = provider;
            this.FileName                   = fileName;
            this.hierarchyItems             = EmptySet;
            this.lastModifiedTimeScannedUtc = MinDateTimeUtc;

            try
            {
                this.fileInfo = new FileInfo(fileName);
                this.scanInfo = ScanInfo.Get(this);
            }
            catch (Exception ex)
            {
                // We might not have access to the file, or the fileName parameter might contain a non-file name.
                // The latter condition should be very rare now since the caller is using FileUtility.IsValidPath.
                // An invalid file name should only get through to here if it's valid per Windows standard naming
                // rules but invalid on the target file system (e.g., if it's on a Unix system or on a CD).
                if (!IsAccessException(ex) && !(ex is NotSupportedException || ex is ArgumentException))
                {
                    throw;
                }

                // Make sure this FileItem is unscannable so nothing will try to use its null this.fileInfo member.
                this.scanInfo = ScanInfo.Unscannable;
            }
        }
Beispiel #2
0
            private void MergeExtensions(
                List <string> extensionList,
                HashSet <Delimiter> delimiters,
                HashSet <Language> languageValues,
                HashSet <string> binaryExtensions)
            {
                ScanInfo scanInfo = new ScanInfo(delimiters, languageValues);

                foreach (string extension in extensionList)
                {
                    if (binaryExtensions.Contains(extension))
                    {
                        // If we get this error, then ScanInfo.xml has assigned the extension as both binary and non-binary.
                        throw new InvalidOperationException(extension + " has already been listed as a binary extension in ScanInfo.xml.");
                    }

                    ScanInfo existingScanInfo;
                    if (this.extensions.TryGetValue(extension, out existingScanInfo))
                    {
                        ScanInfo mergedScanInfo = ScanInfo.Merge(scanInfo, existingScanInfo);
                        this.extensions[extension] = mergedScanInfo;
                    }
                    else
                    {
                        this.extensions.TryAdd(extension, scanInfo);
                    }
                }
            }
Beispiel #3
0
        private static ScanInfo Merge(ScanInfo scanInfo1, ScanInfo scanInfo2)
        {
            ScanInfo result = new ScanInfo(
                scanInfo1.delimiters.Concat(scanInfo2.delimiters),
                scanInfo1.languages.Concat(scanInfo2.languages));

            return(result);
        }
Beispiel #4
0
        private static bool TryGetCustomExtensionScanInfo(string extension, Cache cache, ref ScanInfo scanInfo)
        {
            bool result = false;

            MainPackage package = MainPackage.Instance;

            if (package != null && !string.IsNullOrEmpty(extension) && extension.Length > 1 && extension[0] == '.')
            {
                using (RegistryKey studioUserRoot = package.UserRegistryRoot)
                {
                    if (studioUserRoot != null)
                    {
                        // See if this is a custom file extension mapped to a language service.
                        string extLogViewId = null;
                        using (RegistryKey extKey = studioUserRoot.OpenSubKey(@"FileExtensionMapping\" + extension.Substring(1)))
                        {
                            if (extKey != null)
                            {
                                extLogViewId = (string)extKey.GetValue("LogViewID");
                            }
                        }

                        // If we found a LogViewID, then find which language service it goes with (if any).
                        if (!string.IsNullOrEmpty(extLogViewId))
                        {
                            ScanInfo matchedScanInfo = null;
                            ScanLanguageServices(
                                studioUserRoot,
                                (langName, langGuid) =>
                            {
                                bool matched = false;
                                if (string.Equals(langGuid, extLogViewId, StringComparison.OrdinalIgnoreCase))
                                {
                                    Language language = Utilities.GetLanguage(langName, extension);
                                    ScanInfo languageScanInfo;
                                    if (cache.TryGet(language, out languageScanInfo))
                                    {
                                        matchedScanInfo = languageScanInfo;
                                        matched         = true;
                                    }
                                }

                                return(matched);
                            });

                            if (matchedScanInfo != null)
                            {
                                scanInfo = matchedScanInfo;
                                result   = true;
                            }
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #5
0
        public static bool TryGet(Language language, out ScanInfo scanInfo)
        {
            scanInfo = null;

            bool result = language != Language.Unknown &&
                          language != Language.PlainText &&
                          LazyCache.Value.TryGet(language, out scanInfo) &&
                          scanInfo != null &&
                          scanInfo.IsScannable;

            return(result);
        }
Beispiel #6
0
        public static ScanInfo Get(FileItem file)
        {
            ScanInfo result;
            Cache    cache     = LazyCache.Value;
            string   extension = Path.GetExtension(file.FileName);

            if (cache.TryGet(extension, out result))
            {
                // Binary extensions will return the Unscannable instance.
                if (result.IsScannable)
                {
                    // If the file is open in a document that is using a language that doesn't match one
                    // associated with its file extension, then we need to include the language's info too.
                    // We won't do this for PlainText because it has no comment delimiter, which can
                    // cause ambiguities and duplicates if it's paired with an extension with known
                    // delimiters.  For example, .bat files have delimiters, but they open as PlainText.
                    Language docLanguage = file.DocumentLanguage;
                    if (docLanguage != Language.Unknown &&
                        docLanguage != Language.PlainText &&
                        !result.languages.Contains(docLanguage))
                    {
                        ScanInfo languageScanInfo;
                        if (cache.TryGet(docLanguage, out languageScanInfo))
                        {
                            result = ScanInfo.Merge(result, languageScanInfo);
                        }
                    }
                }
            }
            else
            {
                // The file's extension is unknown, so try to match it by language if a document is open.
                // This allows us to handle user-assigned extensions (e.g., .scs for C#).
                Language docLanguage = file.DocumentLanguage;
                if (docLanguage != Language.Unknown)
                {
                    cache.TryGet(docLanguage, out result);
                }

                if (result == null)
                {
                    result = Infer(file, cache);
                }
            }

            return(result ?? Unscannable);
        }
Beispiel #7
0
        private static ScanInfo Infer(FileItem file, Cache cache)
        {
            ScanInfo result = Unscannable;

            try
            {
                FileInfo fileInfo = new FileInfo(file.FileName);

                // The largest hand-maintained source code file I've ever encountered was almost 900K (in G. Millennium),
                // and it was over 25000 lines of spaghetti code.  So I'm going to assume any file that's over 1MB
                // in size is either generated text or a binary file.
                const long MaxTextFileSize = 1048576;
                if (fileInfo.Exists && fileInfo.Length > 0 && fileInfo.Length <= MaxTextFileSize)
                {
                    string extension = fileInfo.Extension;
                    if (TryGetCustomExtensionScanInfo(extension, cache, ref result))
                    {
                        cache.TryAdd(extension, result);
                    }
                    else
                    {
                        byte[] buffer = ReadInitialBlock(file, fileInfo);
                        if (buffer != null && IsTextBuffer(buffer))
                        {
                            // Use Language instead of .xml or .txt extensions here since a user could override those extensions.
                            Language language = IsXmlBuffer(buffer) ? Language.XML : Language.PlainText;
                            result = cache.Get(language);

                            // Since we were actually able to read a buffer from the file, we'll save
                            // this ScanInfo for use with other files using the same extension.
                            cache.TryAdd(extension, result);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (!FileItem.IsAccessException(ex))
                {
                    throw;
                }

                result = Unscannable;
            }

            return(result);
        }
Beispiel #8
0
            public bool TryAdd(string extension, ScanInfo scanInfo)
            {
                bool result = this.extensions.TryAdd(extension, scanInfo);

                return(result);
            }
Beispiel #9
0
            public bool TryGet(Language language, out ScanInfo scanInfo)
            {
                bool result = this.languages.TryGetValue(language, out scanInfo);

                return(result);
            }
Beispiel #10
0
            public bool TryGet(string extension, out ScanInfo scanInfo)
            {
                bool result = this.extensions.TryGetValue(extension, out scanInfo);

                return(result);
            }