示例#1
0
        /// <inheritdoc cref="Solution.GetOriginatingProjectId"/>
        public ProjectId?GetOriginatingProjectId(ISymbol?symbol)
        {
            if (symbol == null)
            {
                return(null);
            }

            var projectId = GetOriginatingProjectIdWorker(symbol);

            // Validate some invariants we think should hold.  We want to know if this breaks, which indicates some part
            // of our system not working as we might expect.  If they break, create NFWs so we can find out and
            // investigate.

            if (SymbolKey.IsBodyLevelSymbol(symbol))
            {
                // If this is a method-body-level symbol, then we will have it's syntax tree.  Since  we already have a
                // mapping from syntax-trees to docs, so we can immediately map this back to it's originating project.
                //
                // Note: we don't do this for all source symbols, only method-body-level ones.  That's because other
                // source symbols may be *retargetted*.  So you can have the same symbol retargetted into multiple
                // projects, but which have the same syntax-tree (which is only in one project).  We need to actually
                // check it's assembly symbol so that we get the actual project it is from (the original project, or the
                // retargetted project).
                var syntaxTree = symbol.Locations[0].SourceTree;
                Contract.ThrowIfNull(syntaxTree);

                var documentId = this.GetDocumentState(syntaxTree, projectId: null)?.Id;
                if (documentId == null)
                {
                    try
                    {
                        throw new InvalidOperationException(
                                  $"We should always be able to map a body symbol back to a document:\r\n{symbol.Kind}\r\n{symbol.Name}\r\n{syntaxTree.FilePath}\r\n{projectId}"
                                  );
                    }
                    catch (Exception ex) when(FatalError.ReportAndCatch(ex))
                    {
                    }
                }
                else if (documentId.ProjectId != projectId)
                {
                    try
                    {
                        throw new InvalidOperationException(
                                  $"Syntax tree for a body symbol should map to the same project as the body symbol's assembly:\r\n{symbol.Kind}\r\n{symbol.Name}\r\n{syntaxTree.FilePath}\r\n{projectId}\r\n{documentId.ProjectId}"
                                  );
                    }
                    catch (Exception ex) when(FatalError.ReportAndCatch(ex))
                    {
                    }
                }
            }

            return(projectId);
        }