com.google.dart.java2dart.engine.MainAnalysisServer.java Source code

Java tutorial

Introduction

Here is the source code for com.google.dart.java2dart.engine.MainAnalysisServer.java

Source

/*
 * Copyright (c) 2014, the Dart project authors.
 * 
 * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package com.google.dart.java2dart.engine;

import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.dart.engine.AnalysisEngine;
import com.google.dart.engine.ast.AsExpression;
import com.google.dart.engine.ast.AstNode;
import com.google.dart.engine.ast.ClassDeclaration;
import com.google.dart.engine.ast.CompilationUnit;
import com.google.dart.engine.ast.CompilationUnitMember;
import com.google.dart.engine.ast.Expression;
import com.google.dart.engine.ast.ParenthesizedExpression;
import com.google.dart.engine.ast.visitor.NodeLocator;
import com.google.dart.engine.context.AnalysisContext;
import com.google.dart.engine.context.AnalysisErrorInfo;
import com.google.dart.engine.context.AnalysisResult;
import com.google.dart.engine.context.ChangeSet;
import com.google.dart.engine.error.AnalysisError;
import com.google.dart.engine.error.HintCode;
import com.google.dart.engine.sdk.DirectoryBasedDartSdk;
import com.google.dart.engine.source.DartUriResolver;
import com.google.dart.engine.source.FileBasedSource;
import com.google.dart.engine.source.FileUriResolver;
import com.google.dart.engine.source.PackageUriResolver;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.source.SourceFactory;
import com.google.dart.engine.utilities.io.PrintStringWriter;
import com.google.dart.java2dart.Context;
import com.google.dart.java2dart.processor.BeautifySemanticProcessor;
import com.google.dart.java2dart.processor.CollectionSemanticProcessor;
import com.google.dart.java2dart.processor.GuavaSemanticProcessor;
import com.google.dart.java2dart.processor.IOSemanticProcessor;
import com.google.dart.java2dart.processor.JUnitSemanticProcessor;
import com.google.dart.java2dart.processor.ObjectSemanticProcessor;
import com.google.dart.java2dart.processor.PropertySemanticProcessor;
import com.google.dart.java2dart.processor.RenameConstructorsSemanticProcessor;
import com.google.dart.java2dart.processor.SemanticProcessor;
import com.google.dart.java2dart.processor.TypeSemanticProcessor;
import com.google.dart.java2dart.processor.UniqueMemberNamesSemanticProcessor;
import com.google.dart.java2dart.util.ToFormattedSourceVisitor;

import static com.google.dart.java2dart.util.AstFactory.importDirective;
import static com.google.dart.java2dart.util.AstFactory.importHideCombinator;
import static com.google.dart.java2dart.util.AstFactory.importShowCombinator;
import static com.google.dart.java2dart.util.AstFactory.libraryDirective;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
 * Translates some parts of "com.google.dart.engine" project.
 */
public class MainAnalysisServer {
    static class Edit {
        public final int offset;
        public final int length;
        public final String replacement;

        public Edit(int offset, int length, String replacement) {
            this.offset = offset;
            this.length = length;
            this.replacement = replacement;
        }

        @Override
        public String toString() {
            return (offset < 0 ? "(" : "X(") + "offset: " + offset + ", length " + length + ", replacement :>"
                    + replacement + "<:)";
        }

    }

    private static final Context context = new Context();
    private static File engineFolder;
    private static File serverFolder;
    private static File serviceFolder;

    private static CompilationUnit dartUnit;

    private static final String HEADER = "// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file\n"
            + "// for details. All rights reserved. Use of this source code is governed by a\n"
            + "// BSD-style license that can be found in the LICENSE file.\n" + "\n"
            + "// This code was auto-generated, is not intended to be edited, and is subject to\n"
            + "// significant change. Please see the README file for more information.\n\n";

    public static void main(String[] args) throws Exception {
        if (args.length != 2) {
            System.out.println("Usage: java2dart <services-target-src-folder> <server-target-src-folder>");
            System.exit(0);
        }
        String targetFolderServices = args[0];
        String targetFolderServer = args[1];
        System.out.println("Generating files into\n\t" + targetFolderServices + "\n\t" + targetFolderServer);
        new File(targetFolderServer).mkdirs();
        //
        engineFolder = new File("../../../tools/plugins/com.google.dart.engine/src");
        serviceFolder = new File("../../../tools/plugins/com.google.dart.engine.services/src");
        serverFolder = new File("../../../tools/plugins/com.google.dart.server/src");
        engineFolder = engineFolder.getCanonicalFile();
        // configure Context
        context.addClasspathFile(new File("../../../../third_party/guava/r13/guava-13.0.1.jar"));
        context.addClasspathFile(new File("../../../../third_party/commons-lang/3.2.1/commons-lang3-3.2.1.jar"));
        context.addClasspathFile(new File("../../../../third_party/junit/v4_8_2/junit.jar"));
        context.addSourceFolder(engineFolder);
        context.addSourceFolder(serviceFolder);
        context.addSourceFolder(serverFolder);
        context.addSourceFiles(new File(engineFolder, "com/google/dart/engine/"));
        context.addSourceFiles(new File(serverFolder, "com/google/dart/server/"));
        context.removeSourceFiles(new File(serverFolder, "com/google/dart/server/internal/remote/"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/assist"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/change"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/completion"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/correction"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/internal/completion"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/internal/correction"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/internal/refactoring"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/internal/util"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/refactoring"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/status"));
        context.addSourceFiles(new File(serviceFolder, "com/google/dart/engine/services/util"));
        // translate into single CompilationUnit
        dartUnit = context.translate();
        // run processors
        {
            List<SemanticProcessor> PROCESSORS = ImmutableList.of(new TypeSemanticProcessor(context),
                    new ObjectSemanticProcessor(context), new CollectionSemanticProcessor(context),
                    new IOSemanticProcessor(context), new PropertySemanticProcessor(context),
                    new GuavaSemanticProcessor(context), new JUnitSemanticProcessor(context),
                    new EngineAnnotationProcessor(context), new UniqueMemberNamesSemanticProcessor(context),
                    new RenameConstructorsSemanticProcessor(context), new EngineSemanticProcessor(context),
                    new EngineInstanceOfProcessor(context), new BeautifySemanticProcessor(context));
            for (SemanticProcessor processor : PROCESSORS) {
                processor.process(dartUnit);
            }
        }
        // run this again, because we may introduce conflicts when convert methods to getters/setters
        context.ensureUniqueClassMemberNames();
        context.applyLocalVariableSemanticChanges(dartUnit);
        {
            CompilationUnit library = buildServiceInterfacesLibrary();
            Files.write(getFormattedSource(library), new File(targetFolderServer + "/service_interfaces.dart"),
                    Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServiceComputersLibrary();
            Files.write(getFormattedSource(library), new File(targetFolderServer + "/service_computers.dart"),
                    Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServicesLibrary_change();
            Files.write(getFormattedSource(library), new File(targetFolderServices + "/change.dart"),
                    Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServicesLibrary_completion();
            String source = getFormattedSource(library);
            // TODO(scheglov) improve java2dart to make this translated correctly
            source = replaceSourceFragment(source,
                    "new CompletionEngine_CommentReferenceCompleter(this, _completionNode)",
                    "new CompletionEngine_CommentReferenceCompleter(CompletionEngine_this, _completionNode)");
            source = replaceSourceFragment(source,
                    "new CompletionEngine_TypeNameCompleter(this, _completionNode, node)",
                    "new CompletionEngine_TypeNameCompleter(CompletionEngine_this, _completionNode, node)");
            //      source = replaceSourceFragment(
            //          source,
            //          "new CompletionEngine_NameCollector(this)",
            //          "new CompletionEngine_NameCollector(CompletionEngine_this)");
            source = replaceSourceFragment(source, "new CompletionEngine_IdentifierCompleter(this, node)",
                    "new CompletionEngine_IdentifierCompleter(CompletionEngine_this, node)");
            source = replaceSourceFragment(source, "new CompletionEngine_StringCompleter(this, node)",
                    "new CompletionEngine_StringCompleter(CompletionEngine_this, node)");
            Files.write(source, new File(targetFolderServices + "/completion.dart"), Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServicesLibrary_status();
            Files.write(getFormattedSource(library), new File(targetFolderServices + "/status.dart"),
                    Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServicesLibrary_proposal();
            Files.write(getFormattedSource(library), new File(targetFolderServices + "/proposal.dart"),
                    Charsets.UTF_8);
        }
        {
            CompilationUnit library = buildServicesLibrary_util();
            Files.write(getFormattedSource(library), new File(targetFolderServices + "/util.dart"), Charsets.UTF_8);
        }
        // TODO(scheglov) restore to translate more
        //    {
        //      CompilationUnit library = buildServicesLibrary_assist();
        //      Files.write(getFormattedSource(library), new File(targetFolder2
        //          + "/service_correction.dart"), Charsets.UTF_8);
        //    }
        {
            CompilationUnit library = buildServicesLibrary_refactoring();
            Files.write(getFormattedSource(library), new File(targetFolderServices + "/refactoring.dart"),
                    Charsets.UTF_8);
        }
        {
            String projectFolder = new File(targetFolderServices).getParentFile().getParentFile().getParent();
            fixUnnecessaryCastHints(projectFolder);
        }
        {
            String projectFolder = new File(targetFolderServer).getParentFile().getParentFile().getParent();
            fixUnnecessaryCastHints(projectFolder);
        }
        System.out.println("Translation complete");
    }

    private static void addNotRemovedCompiationUnitEntries(CompilationUnit targetUnit,
            List<CompilationUnitMember> members) {
        for (CompilationUnitMember member : members) {
            // may be removed
            CompilationUnit memberUnit = (CompilationUnit) member.getParent();
            if (memberUnit == null || !memberUnit.getDeclarations().contains(member)) {
                continue;
            }
            // OK, add this member
            targetUnit.getDeclarations().add(member);
        }
    }

    private static void applyEdits(File file, List<Edit> edits) throws IOException {
        // sort in descending order
        Collections.sort(edits, new Comparator<Edit>() {
            @Override
            public int compare(Edit o1, Edit o2) {
                return o2.offset - o1.offset;
            }
        });
        // apply to file
        String content = Files.toString(file, Charsets.UTF_8);
        for (Edit edit : edits) {
            content = content.substring(0, edit.offset) + edit.replacement
                    + content.substring(edit.offset + edit.length);
        }
        Files.write(content, file, Charsets.UTF_8);
    }

    private static CompilationUnit buildServiceComputersLibrary() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("service", "computers"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null,
                importShowCombinator("JavaStringBuilder", "StringUtils")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_engine.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null,
                importShowCombinator("Source")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/scanner.dart", null,
                importShowCombinator("Token")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", "pae"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null,
                importShowCombinator("DartType")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null));
        unit.getDirectives().add(importDirective("service_interfaces.dart", "psi"));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServerPath(file, "internal/local/computer/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        EngineSemanticProcessor.useImportPrefix(context, unit, "psi", new String[] { "com.google.dart.server." },
                true);
        EngineSemanticProcessor.useImportPrefix(context, unit, "pae",
                new String[] { "com.google.dart.engine.element." }, false);
        return unit;
    }

    private static CompilationUnit buildServiceInterfacesLibrary() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("service", "interfaces"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null,
                importShowCombinator("Enum", "StringUtils")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null,
                importShowCombinator("Source")));
        unit.getDirectives().add(importDirective("package:analysis_services/src/generated/change.dart", null,
                importShowCombinator("SourceChange")));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServerPath(file, "AssistsConsumer.java") || isServerPath(file, "CompletionSuggestion.java")
                    || isServerPath(file, "CompletionSuggestionKind.java") || isServerPath(file, "Consumer.java")
                    || isServerPath(file, "Element.java") || isServerPath(file, "ElementKind.java")
                    || isServerPath(file, "HighlightRegion.java") || isServerPath(file, "HighlightType.java")
                    || isServerPath(file, "ListSourceSet.java") || isServerPath(file, "NavigationRegion.java")
                    || isServerPath(file, "NotificationKind.java") || isServerPath(file, "Outline.java")
                    || isServerPath(file, "OutlineKind.java") || isServerPath(file, "SearchResult.java")
                    || isServerPath(file, "SearchResultKind.java")
                    || isServerPath(file, "SearchResultsConsumer.java") || isServerPath(file, "SourceRegion.java")
                    || isServerPath(file, "SourceSet.java") || isServerPath(file, "SourceSetKind.java")
                    || isServerPath(file, "TypeHierarchyItem.java")
                    || isServerPath(file, "internal/local/ImplicitSourceSet.java")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_assist() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("service", "correction"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/engine.dart", null,
                importShowCombinator("AnalysisContext")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/error.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null,
                importHideCombinator("StringUtils")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_io.dart", null,
                importShowCombinator("JavaFile")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/parser.dart", null,
                importShowCombinator("ParserErrorCode")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/scanner.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/sdk.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source_io.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/utilities_dart.dart", null));
        unit.getDirectives().add(importDirective("change.dart", null));
        unit.getDirectives().add(importDirective("proposal.dart", null));
        unit.getDirectives().add(importDirective("stubs.dart", null));
        unit.getDirectives().add(importDirective("util.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isCorrectionProposalFile(file)) {
                continue;
            }
            if (isCorrectionUtilFile(file)) {
                continue;
            }
            if (isServicePath(file, "assist/") || isServicePath(file, "correction/")
                    || isServicePath(file, "internal/correction/")
                    || isServicePath(file, "internal/util/TokenUtils.java") || isServicePath(file, "util/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_change() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("services", "change"));
        unit.getDirectives().add(importDirective("dart:collection", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_io.dart", null,
                importShowCombinator("JavaFile")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServicePath(file, "change/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_completion() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("services", "completion"));
        unit.getDirectives().add(importDirective("dart:collection", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null,
                importHideCombinator("StringUtils")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_engine.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_io.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/engine.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/error.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/resolver.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/scanner.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/sdk.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source_io.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/utilities_dart.dart", null));
        unit.getDirectives().add(importDirective("stubs.dart", null));
        unit.getDirectives().add(importDirective("util.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServicePath(file, "completion/") || isServicePath(file, "internal/completion/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_proposal() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("services", "proposal"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_io.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null));
        unit.getDirectives().add(importDirective("change.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isCorrectionProposalFile(file)) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_refactoring() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("service", "refactoring"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null));
        //    unit.getDirectives().add(
        //        importDirective(
        //            "package:analyzer/src/generated/engine.dart",
        //            null,
        //            importShowCombinator("AnalysisContext")));
        //    unit.getDirectives().add(importDirective("package:analyzer/src/generated/error.dart", null));
        //    unit.getDirectives().add(
        //        importDirective(
        //            "package:analyzer/src/generated/java_core.dart",
        //            null,
        //            importHideCombinator("StringUtils")));
        //    unit.getDirectives().add(
        //        importDirective(
        //            "package:analyzer/src/generated/java_io.dart",
        //            null,
        //            importShowCombinator("JavaFile")));
        //    unit.getDirectives().add(
        //        importDirective(
        //            "package:analyzer/src/generated/parser.dart",
        //            null,
        //            importShowCombinator("ParserErrorCode")));
        //    unit.getDirectives().add(importDirective("package:analyzer/src/generated/scanner.dart", null));
        //    unit.getDirectives().add(importDirective("package:analyzer/src/generated/sdk.dart", null));
        //    unit.getDirectives().add(importDirective("package:analyzer/src/generated/source_io.dart", null));
        //    unit.getDirectives().add(
        //        importDirective("package:analyzer/src/generated/utilities_dart.dart", null));
        //    unit.getDirectives().add(importDirective("change.dart", null));
        //    unit.getDirectives().add(importDirective("proposal.dart", null));
        //    unit.getDirectives().add(importDirective("stubs.dart", null));
        //    unit.getDirectives().add(importDirective("util.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServicePath(file, "refactoring/") || isServicePath(file, "internal/refactoring/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_status() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("services", "status"));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/engine.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null));
        unit.getDirectives().add(importDirective("stubs.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isServicePath(file, "status/")) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static CompilationUnit buildServicesLibrary_util() throws Exception {
        CompilationUnit unit = new CompilationUnit(null, null, null, null, null);
        unit.getDirectives().add(libraryDirective("services", "util"));
        unit.getDirectives().add(importDirective("dart:collection", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/java_core.dart", null,
                importHideCombinator("StringUtils")));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/ast.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/element.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/engine.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/error.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/resolver.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/source.dart", null));
        unit.getDirectives().add(importDirective("package:analyzer/src/generated/scanner.dart", null));
        unit.getDirectives().add(importDirective("change.dart", null));
        unit.getDirectives().add(importDirective("proposal.dart", null));
        unit.getDirectives().add(importDirective("status.dart", null));
        unit.getDirectives().add(importDirective("stubs.dart", null));
        for (Entry<File, List<CompilationUnitMember>> entry : context.getFileToMembers().entrySet()) {
            File file = entry.getKey();
            if (isCorrectionUtilFile(file)) {
                addNotRemovedCompiationUnitEntries(unit, entry.getValue());
            }
        }
        return unit;
    }

    private static void fixUnnecessaryCastHints(String projectPath) throws Exception {
        System.out.println();
        System.out.println("Removing unnecessary casts.");
        AnalysisContext context = AnalysisEngine.getInstance().createAnalysisContext();
        DirectoryBasedDartSdk sdk = DirectoryBasedDartSdk.getDefaultSdk();
        SourceFactory sourceFactory = new SourceFactory(new DartUriResolver(sdk), new FileUriResolver(),
                new PackageUriResolver(new File(projectPath + "/packages")));
        context.setSourceFactory(sourceFactory);
        // prepare sources
        List<Source> sources = Lists.newArrayList();
        Map<Source, File> sourceToFile = Maps.newHashMap();
        for (File file : FileUtils.listFiles(new File(projectPath + "/lib/src/generated"), new String[] { "dart" },
                true)) {
            if (file.getAbsolutePath().contains("/packages/")) {
                continue;
            }
            FileBasedSource source = new FileBasedSource(file);
            sources.add(source);
            sourceToFile.put(source, file);
        }
        // add sources to AnalysisContext
        {
            ChangeSet changeSet = new ChangeSet();
            for (Source source : sources) {
                changeSet.addedSource(source);
            }
            context.applyChanges(changeSet);
        }
        System.out.println(sources.size() + " sources to analyze.");
        // perform analysis
        while (true) {
            AnalysisResult analysisResult = context.performAnalysisTask();
            if (analysisResult.getChangeNotices() == null) {
                break;
            }
        }
        System.out.println("Analysis done.");
        // process errors
        for (Source source : sources) {
            CompilationUnit unit = context.parseCompilationUnit(source);
            List<Edit> edits = Lists.newArrayList();
            AnalysisErrorInfo errorInfo = context.getErrors(source);
            AnalysisError[] errors = errorInfo.getErrors();
            for (AnalysisError error : errors) {
                if (error.getErrorCode() == HintCode.UNNECESSARY_CAST) {
                    AstNode node = new NodeLocator(error.getOffset()).searchWithin(unit);
                    AsExpression asExpression = node.getAncestor(AsExpression.class);
                    if (asExpression != null) {
                        // remove "as" and its enclosing ()
                        AstNode enclosing = asExpression;
                        if (enclosing.getParent() instanceof ParenthesizedExpression) {
                            enclosing = enclosing.getParent();
                        }
                        // add Edit
                        Expression expr = asExpression.getExpression();
                        int enOffset = enclosing.getOffset();
                        int exEnd = expr.getEnd();
                        edits.add(new Edit(enOffset, expr.getOffset() - enOffset, ""));
                        edits.add(new Edit(exEnd, enclosing.getEnd() - exEnd, ""));
                    }
                }
            }
            // apply edits to file
            File file = sourceToFile.get(source);
            applyEdits(file, edits);
        }
        System.out.println("Edits applied.");
        System.out.println();
    }

    /**
     * @return the formatted Dart source dump of the given {@link AstNode}.
     */
    private static String getFormattedSource(CompilationUnit unit) {
        PrintStringWriter writer = new PrintStringWriter();
        writer.append(HEADER);
        sortUnitMembersByName(unit);
        unit.accept(new ToFormattedSourceVisitor(writer));
        String source = writer.toString();
        source = removeTrailingWhitespaces(source);
        return source;
    }

    private static boolean isCorrectionProposalFile(File file) throws Exception {
        return isServicePath(file, "correction/AddDependencyCorrectionProposal.java")
                || isServicePath(file, "correction/ChangeCorrectionProposal.java")
                || isServicePath(file, "correction/CorrectionImage.java")
                || isServicePath(file, "correction/CorrectionKind.java")
                || isServicePath(file, "correction/CorrectionProposal.java")
                || isServicePath(file, "correction/CreateFileCorrectionProposal.java")
                || isServicePath(file, "correction/LinkedPositionProposal.java")
                || isServicePath(file, "correction/SourceCorrectionProposal.java");
    }

    private static boolean isCorrectionUtilFile(File file) throws Exception {
        return isServicePath(file, "assist/AssistContext.java") || isServicePath(file, "util/HierarchyUtils.java")
                || isServicePath(file, "util/NameOccurrencesFinder.java")
                || isServicePath(file, "util/SelectionAnalyzer.java")
                || isServicePath(file, "internal/correction/CorrectionUtils.java")
                || isServicePath(file, "internal/correction/SourceBuilder.java")
                || isServicePath(file, "internal/correction/StatementAnalyzer.java")
                || isServicePath(file, "internal/correction/URIUtils.java")
                || isServicePath(file, "internal/util/TokenUtils.java");
    }

    /**
     * @param serverPackage the sub-package in <code>com/google/dart/server</code>.
     * @return <code>true</code> if given {@link File} is located in sub-package of Engine project.
     */
    private static boolean isServerPath(File file, String serverPackage) throws Exception {
        String filePath = file.getCanonicalPath();
        String prefix = serverFolder.getCanonicalPath() + "/com/google/dart/server/" + serverPackage;
        return filePath.startsWith(prefix);
    }

    /**
     * @param servicePackage the sub-package in <code>com/google/dart/engine/services</code>.
     * @return <code>true</code> if given {@link File} is located in sub-package of Engine project.
     */
    private static boolean isServicePath(File file, String servicePackage) throws Exception {
        String filePath = file.getCanonicalPath();
        String prefix = serviceFolder.getCanonicalPath() + "/com/google/dart/engine/services/" + servicePackage;
        return filePath.startsWith(prefix);
    }

    /**
     * Removes trailing spaces from the given Dart source.
     */
    private static String removeTrailingWhitespaces(String source) {
        String[] lines = StringUtils.splitPreserveAllTokens(source, '\n');
        for (int i = 0; i < lines.length; i++) {
            lines[i] = StringUtils.stripEnd(lines[i], null);
        }
        return StringUtils.join(lines, "\n");
    }

    /**
     * Replaces the fragment of the source specified by the RE pattern with the given source.
     * 
     * @param source the source to replace fragment in
     * @param pattern the fragment to replace
     * @param replacement the source to replace fragment with
     * @return the source with the replacement fragment
     */
    private static String replaceSourceFragment(String source, String pattern, String replacement) {
        int index = source.indexOf(pattern);
        if (index == -1) {
            throw new IllegalArgumentException("Not found: " + pattern);
        }
        return StringUtils.replace(source, pattern, replacement);
    }

    private static void sortUnitMembersByName(CompilationUnit unit) {
        Collections.sort(unit.getDeclarations(), new Comparator<CompilationUnitMember>() {
            @Override
            public int compare(CompilationUnitMember o1, CompilationUnitMember o2) {
                String name1 = ((ClassDeclaration) o1).getName().getName();
                String name2 = ((ClassDeclaration) o2).getName().getName();
                return name1.compareTo(name2);
            }
        });
    }
}