/// <summary>
 /// Walks the supplied System.CodeDom.CodeCompileUnit and produces a corresponding CompilationUnit.
 /// Enters declarations into the supplied Module and errors into the supplied ErrorNodeList. 
 /// Calls back to the supplied compiler to resolve assembly references and to create appropriate documents for code snippets.
 /// </summary>
 /// <param name="compiler">Called upon to resolve assembly references and to create Documents for snippets.</param>
 /// <param name="compilationUnit">The root of the CodeDOM tree to be translated into an IR CompileUnit.</param>
 /// <param name="targetModule">The module or assembly to which the compilation unit will be compiled.</param>
 /// <param name="errorNodes">Errors in the CodeDOM tree that are found during translation are added to this list.</param>
 /// <returns></returns>
 public CompilationUnit Translate(Compiler compiler, CodeCompileUnit compilationUnit, Module targetModule, ErrorNodeList errorNodes){
   Debug.Assert(compiler != null); 
   Debug.Assert(compilationUnit != null); 
   Debug.Assert(targetModule != null); 
   Debug.Assert(errorNodes != null);
   this.compiler = compiler;
   this.errorNodes = errorNodes;
   this.targetModule = targetModule;
   CodeSnippetCompileUnit cscu = compilationUnit as CodeSnippetCompileUnit;
   CompilationUnit cunit = cscu != null ? new CompilationUnitSnippet() : new CompilationUnit();
   this.Translate(compilationUnit.AssemblyCustomAttributes, targetModule.Attributes);
   StringCollection references = compilationUnit.ReferencedAssemblies;
   if (references != null && references.Count > 0){
     AssemblyReferenceList arefs = targetModule.AssemblyReferences;
     TrivialHashtable alreadyReferencedAssemblies = new TrivialHashtable();
     for (int i = 0, n = arefs.Count; i < n; i++)
       alreadyReferencedAssemblies[arefs[i].Assembly.UniqueKey] = this;
     foreach (string rAssemblyName in references)
       compiler.AddAssemblyReferenceToModule(null, targetModule, rAssemblyName, null, errorNodes, alreadyReferencedAssemblies, false);
   }
   Namespace defaultNamespace = new Namespace(Identifier.Empty, Identifier.Empty, null, null, new NamespaceList(), null);
   NamespaceList nspaceList = defaultNamespace.NestedNamespaces;
   CodeNamespaceCollection nspaces = compilationUnit.Namespaces;
   if (nspaces != null) 
     foreach (CodeNamespace cns in nspaces) 
       nspaceList.Add(this.Translate(cns));
   if (cscu == null) return cunit;
   Document doc = null;
   if (cscu.LinePragma == null)
     doc = compiler.CreateDocument(targetModule.Name, 1, cscu.Value);
   else{
     doc = compiler.CreateDocument(cscu.LinePragma.FileName, cscu.LinePragma.LineNumber, cscu.Value);
     cunit.Name = Identifier.For(cscu.LinePragma.FileName);
   }
   cunit.SourceContext = new SourceContext(doc);
   defaultNamespace.SourceContext = cunit.SourceContext;
   return cunit;
 }
Example #2
0
    public override void ParseAndAnalyzeCompilationUnit(string fname, string text, int line, int col, ErrorNodeList errors, Compilation compilation, AuthoringSink sink) {
      if (fname == null || text == null || errors == null || compilation == null){Debug.Assert(false); return;}
      if (compilation != null && compilation.CompilerParameters is SpecSharpCompilerOptions)
        this.allowSpecSharpExtensions = !((SpecSharpCompilerOptions)compilation.CompilerParameters).Compatibility;
      CompilationUnitList compilationUnitSnippets = compilation.CompilationUnits;
      if (compilationUnitSnippets == null){Debug.Assert(false); return;}
      //Fix up the CompilationUnitSnippet corresponding to fname with the new source text
      CompilationUnitSnippet cuSnippet = this.GetCompilationUnitSnippet(compilation, fname);
      if (cuSnippet == null) return;
      Compiler compiler = new Compiler();
      compiler.CurrentCompilation = compilation;
      cuSnippet.SourceContext.Document = compiler.CreateDocument(fname, 1, new DocumentText(text));
      cuSnippet.SourceContext.EndPos = text.Length;
      //Parse all of the compilation unit snippets
      Module symbolTable = compilation.TargetModule = compiler.CreateModule(compilation.CompilerParameters, errors);
      AttributeList assemblyAttributes = symbolTable is AssemblyNode ? symbolTable.Attributes : null;
      AttributeList moduleAttributes = symbolTable is AssemblyNode ? ((AssemblyNode)symbolTable).ModuleAttributes : symbolTable.Attributes;
      int n = compilationUnitSnippets.Count;
      for (int i = 0; i < n; i++){
        CompilationUnitSnippet compilationUnitSnippet = compilationUnitSnippets[i] as CompilationUnitSnippet;
        if (compilationUnitSnippet == null){Debug.Assert(false); continue;}
        Document doc = compilationUnitSnippet.SourceContext.Document;
        doc = compilationUnitSnippet.SourceContext.Document;
        if (doc == null || doc.Text == null){Debug.Assert(false); continue;}
        IParserFactory factory = compilationUnitSnippet.ParserFactory;
        if (factory == null) continue;
        compilationUnitSnippet.Nodes = null;
        compilationUnitSnippet.PreprocessorDefinedSymbols = null;
        IParser p = factory.CreateParser(doc.Name, doc.LineNumber, doc.Text, symbolTable, compilationUnitSnippet == cuSnippet ? errors : new ErrorNodeList(), compilation.CompilerParameters);
        if (p == null){Debug.Assert(false); continue;}
        if (p is ResgenCompilerStub) continue;
        Parser specSharpParser = p as Parser;
        if (specSharpParser == null)
          p.ParseCompilationUnit(compilationUnitSnippet);
        else
          specSharpParser.ParseCompilationUnit(compilationUnitSnippet, compilationUnitSnippet != cuSnippet, false);
        //TODO: this following is a good idea only if the files will not be frequently reparsed from source
        //StringSourceText stringSourceText = doc.Text.TextProvider as StringSourceText;
        //if (stringSourceText != null && stringSourceText.IsSameAsFileContents)
        //  doc.Text.TextProvider = new CollectibleSourceText(doc.Name, doc.Text.Length);
      }
      //Construct symbol table for entire project
      ErrorHandler errorHandler = new ErrorHandler(errors);
      SpecSharpCompilation ssCompilation = new SpecSharpCompilation();
      TrivialHashtable ambiguousTypes = new TrivialHashtable();
      TrivialHashtable referencedLabels = new TrivialHashtable();
      TrivialHashtable scopeFor = this.scopeFor = new TrivialHashtable();
      Scoper scoper = new Scoper(scopeFor);
      scoper.currentModule = symbolTable;
      Looker symLooker = new Looker(null, new ErrorHandler(new ErrorNodeList(0)), scopeFor, ambiguousTypes, referencedLabels);
      symLooker.currentAssembly = (symLooker.currentModule = symbolTable) as AssemblyNode;
      Looker looker = new Looker(null, errorHandler, scopeFor, ambiguousTypes, referencedLabels);
      looker.currentAssembly = (looker.currentModule = symbolTable) as AssemblyNode;
      looker.VisitAttributeList(assemblyAttributes);
      bool dummyCompilation = compilation.CompilerParameters is SpecSharpCompilerOptions && ((SpecSharpCompilerOptions)compilation.CompilerParameters).DummyCompilation;
      if (dummyCompilation){
        //This happens when there is no project. In this case, semantic errors should be ignored since the references and options are unknown.
        //But proceed with the full analysis anyway so that some measure of Intellisense can still be provided.
        errorHandler.Errors = new ErrorNodeList(0);
      }
      for (int i = 0; i < n; i++){
        CompilationUnit cUnit = compilationUnitSnippets[i];
        scoper.VisitCompilationUnit(cUnit);
      }
      for (int i = 0; i < n; i++){
        CompilationUnit cUnit = compilationUnitSnippets[i];
        if (cUnit == cuSnippet)
          looker.VisitCompilationUnit(cUnit); //Uses real error message list and populate the identifier info lists
        else
          symLooker.VisitCompilationUnit(cUnit); //Errors are discarded
      }
      //Run resolver over symbol table so that custom attributes on member signatures are known and can be used
      //to error check the the given file.
      TypeSystem typeSystem = new TypeSystem(errorHandler);
      Resolver resolver = new Resolver(errorHandler, typeSystem);
      resolver.currentAssembly = (resolver.currentModule = symbolTable) as AssemblyNode;
      Resolver symResolver = new Resolver(new ErrorHandler(new ErrorNodeList(0)), typeSystem);
      symResolver.currentAssembly = resolver.currentAssembly;
      symResolver.VisitAttributeList(assemblyAttributes);
      for (int i = 0; i < n; i++) {
        CompilationUnit cUnit = compilationUnitSnippets[i];
        if (cUnit == cuSnippet)
          resolver.VisitCompilationUnit(cUnit); //Uses real error message list and populate the identifier info lists
        else
          symResolver.VisitCompilationUnit(cUnit); //Errors are discarded
      }
      if (dummyCompilation) return;
      //Now analyze the given file for errors
      Checker checker = new Checker(ssCompilation, errorHandler, typeSystem, scopeFor, ambiguousTypes, referencedLabels);
      checker.currentAssembly = (checker.currentModule = symbolTable) as AssemblyNode;
      checker.VisitAttributeList(assemblyAttributes, checker.currentAssembly);
      checker.VisitModuleAttributes(moduleAttributes);
      checker.VisitCompilationUnit(cuSnippet);
       
      MemberFinder finder = new MemberFinder(line, col);
      finder.VisitCompilationUnit(cuSnippet);
      Node node = finder.Member;
      if (node == null){
        if (line == 0 && col == 0) 
          node = cuSnippet;
        else
          return;
      }

      SpecSharpCompilerOptions options = (SpecSharpCompilerOptions) compilation.CompilerParameters;
      if (options.IsContractAssembly) return;
      ssCompilation.RunPlugins(node, errorHandler);
      Normalizer normalizer = new Normalizer(typeSystem);
      normalizer.Visit(node);
      Analyzer analyzer = new Analyzer(typeSystem, compilation);
      analyzer.Visit(node);

      if (options.RunProgramVerifierWhileEditing)
        ssCompilation.AddProgramVerifierPlugin(typeSystem, compilation);
      ssCompilation.analyzer = analyzer; // make the analyzer available to plugins for access to method CFGs
      ssCompilation.RunPlugins(node, errorHandler);
      ssCompilation.analyzer = null;
      analyzer = null;
    }