Exemple #1
0
    public override void CompileParseTree(Compilation compilation, ErrorNodeList errorNodes){
      if (compilation == null || compilation.CompilationUnits == null || compilation.TargetModule == null){Debug.Assert(false); return;}
      if (compilation.CompilationUnits.Count == 0) return;
      TrivialHashtable ambiguousTypes = new TrivialHashtable();
      TrivialHashtable referencedLabels = new TrivialHashtable();
      TrivialHashtable scopeFor = new TrivialHashtable(64);
      ErrorHandler errorHandler = new ErrorHandler(errorNodes);
      SpecSharpCompilation ssCompilation = new SpecSharpCompilation();
      SpecSharpCompilerOptions options = (SpecSharpCompilerOptions)compilation.CompilerParameters;

      //Attach scopes to namespaces and types so that forward references to base types can be looked up in the appropriate namespace scope
      Scoper scoper = new Scoper(scopeFor);
      scoper.VisitCompilation(compilation);
      scoper = null;

      if (options.NoStandardLibrary && compilation.TargetModule is AssemblyNode) {
        if (compilation.TargetModule.IsValidTypeName(StandardIds.System, StandardIds.CapitalObject)) {
          SystemAssemblyLocation.ParsedAssembly = (AssemblyNode)compilation.TargetModule;
          SystemCompilerRuntimeAssemblyLocation.ParsedAssembly = (AssemblyNode)compilation.TargetModule; //So that mscorlib can have contracts but no reference to another assembly
        } else if (compilation.TargetModule.IsValidTypeName(Identifier.For("System.Compiler"), Identifier.For("ComposerAttribute")))
          SystemCompilerRuntimeAssemblyLocation.ParsedAssembly = (AssemblyNode)compilation.TargetModule;
        else if (compilation.TargetModule.IsValidTypeName(Identifier.For("Microsoft.SpecSharp"), Identifier.For("dummy")))
          RuntimeAssemblyLocation.ParsedAssembly = (AssemblyNode)compilation.TargetModule;
      }
      object ObjectType = SystemTypes.Object;
      if (ObjectType == null) return; //system types did not initialize

      //Walk IR looking up names
      Looker looker = new Looker(compilation.GlobalScope, errorHandler, scopeFor, ambiguousTypes, referencedLabels);
      if (options != null && options.EmitSourceContextsOnly)
      {
        looker.DontInjectDefaultConstructors = true;
      }

      // begin change by drunje
      looker.AllowPointersToManagedStructures = options.AllowPointersToManagedStructures;
      // end change by drunje
      looker.VisitCompilation(compilation);
      looker = null;

      if (options != null && options.EmitSourceContextsOnly) return; // stop after looker to have resolved types

      //Walk IR inferring types and resolving overloads
      TypeSystem typeSystem = new TypeSystem(errorHandler);
      Resolver resolver = new Resolver(errorHandler, typeSystem);
      resolver.VisitCompilation(compilation);
      resolver = null;

      //Walk IR checking for semantic errors and repairing it so that the next walk will work
      Checker checker = new Checker(ssCompilation, errorHandler, typeSystem, scopeFor, ambiguousTypes, referencedLabels);
      checker.VisitCompilation(compilation);
      checker = null;
      scopeFor = null;
      ambiguousTypes = null;
      referencedLabels = null;

      if (!options.IsContractAssembly) {
        if (options.RunProgramVerifier)
          ssCompilation.AddProgramVerifierPlugin(typeSystem, compilation);

        //Allow third party extensions to analyze AST IR for further errors
        ssCompilation.RunPlugins(compilation, errorHandler);
      }

      //Walk IR reducing it to nodes that have predefined mappings to MD+IL
      Normalizer normalizer = new Normalizer(typeSystem);
      normalizer.VisitCompilation(compilation);
      normalizer = null;

      if (options.IsContractAssembly) return;
      //Walk normalized IR instrumenting accesses of fields of guarded classes with checks
      CompilationUnit cu = compilation.CompilationUnits[0];
      if (cu != null && cu.PreprocessorDefinedSymbols != null && cu.PreprocessorDefinedSymbols.ContainsKey("GuardedFieldAccessChecks")){
        if (errorNodes.Count == 0){
          GuardedFieldAccessInstrumenter instrumenter = new GuardedFieldAccessInstrumenter();
          instrumenter.VisitCompilation(compilation);
          instrumenter = null;
        }
      }

      //Walk normalized IR doing code analysis
      Analyzer analyzer = new Analyzer(typeSystem, compilation);
      analyzer.Visit(compilation);

      //Allow third party extensions to analyze normalized IR for further errors
      ssCompilation.analyzer = analyzer; // make the analyzer available to plugins for access to method CFGs
      ssCompilation.RunPlugins(compilation, errorHandler);
      ssCompilation.analyzer = null;
      ssCompilation = null;
      analyzer = null;
      errorHandler = null;

      //Walk IR to optimize code further after analyses were performed, eg. to remove debug only code
      Optimizer optimizer = new Optimizer();
      optimizer.Visit(compilation);
      optimizer = null;
    }
Exemple #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;
    }