com.google.dart.tools.ui.internal.refactoring.ServiceUtils_OLD.java Source code

Java tutorial

Introduction

Here is the source code for com.google.dart.tools.ui.internal.refactoring.ServiceUtils_OLD.java

Source

/*
 * Copyright (c) 2013, 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.tools.ui.internal.refactoring;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.dart.engine.services.change.Change;
import com.google.dart.engine.services.change.CompositeChange;
import com.google.dart.engine.services.change.CreateFileChange;
import com.google.dart.engine.services.change.Edit;
import com.google.dart.engine.services.change.MergeCompositeChange;
import com.google.dart.engine.services.change.SourceChange;
import com.google.dart.engine.services.correction.AddDependencyCorrectionProposal;
import com.google.dart.engine.services.correction.ChangeCorrectionProposal;
import com.google.dart.engine.services.correction.CorrectionImage;
import com.google.dart.engine.services.correction.CorrectionKind;
import com.google.dart.engine.services.correction.CorrectionProposal;
import com.google.dart.engine.services.correction.CreateFileCorrectionProposal;
import com.google.dart.engine.services.correction.LinkedPositionProposal;
import com.google.dart.engine.services.correction.SourceCorrectionProposal;
import com.google.dart.engine.services.status.RefactoringStatus;
import com.google.dart.engine.services.status.RefactoringStatusContext;
import com.google.dart.engine.services.status.RefactoringStatusEntry;
import com.google.dart.engine.services.status.RefactoringStatusSeverity;
import com.google.dart.engine.source.Source;
import com.google.dart.engine.utilities.source.SourceRange;
import com.google.dart.tools.core.DartCore;
import com.google.dart.tools.core.refactoring.CompilationUnitChange;
import com.google.dart.tools.internal.corext.refactoring.base.DartStatusContext_OLD;
import com.google.dart.tools.internal.corext.refactoring.changes.TextChangeCompatibility;
import com.google.dart.tools.internal.corext.refactoring.util.ExecutionUtils;
import com.google.dart.tools.internal.corext.refactoring.util.RunnableObjectEx;
import com.google.dart.tools.ui.DartPluginImages;
import com.google.dart.tools.ui.DartToolsPlugin;
import com.google.dart.tools.ui.internal.text.correction.proposals.LinkedCorrectionProposal_OLD;
import com.google.dart.tools.ui.internal.text.correction.proposals.TrackedPositions;
import com.google.dart.tools.ui.text.dart.IDartCompletionProposal;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.ltk.core.refactoring.TextChange;
import org.eclipse.ltk.core.refactoring.TextEditChangeGroup;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.swt.graphics.Image;
import org.eclipse.text.edits.MalformedTreeException;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.text.edits.TextEditGroup;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Utilities to create LTK wrapper around Engine Services objects.
 * 
 * @coverage dart.editor.ui.refactoring.ui
 */
public class ServiceUtils_OLD {
    /**
     * @return the {@link CoreException} wrapper around given {@link Throwable}.
     */
    public static CoreException createCoreException(Throwable e) {
        IStatus status = createRuntimeStatus(e);
        return new CoreException(status);
    }

    /**
     * @return the LTK change for the given Services {@link Change}.
     */
    public static org.eclipse.ltk.core.refactoring.Change toLTK(Change change) {
        // leaf SourceChange
        if (change instanceof SourceChange) {
            SourceChange sourceChange = (SourceChange) change;
            return toLTK(sourceChange);
        }
        // leaf CreateFileChange
        if (change instanceof CreateFileChange) {
            CreateFileChange fileChange = (CreateFileChange) change;
            return new com.google.dart.tools.ui.internal.text.correction.proposals.CreateFileChange(
                    fileChange.getName(), fileChange.getFile(), fileChange.getContent());
        }
        // may be MergeCompositeChange
        if (change instanceof MergeCompositeChange) {
            MergeCompositeChange mergeChange = (MergeCompositeChange) change;
            return toLTK(mergeChange);
        }
        // should be CompositeChange
        CompositeChange compositeChange = (CompositeChange) change;
        return toLTK(compositeChange);
    }

    /**
     * @return the LTK change for the given Services {@link CompositeChange}.
     */
    public static org.eclipse.ltk.core.refactoring.CompositeChange toLTK(CompositeChange compositeChange) {
        org.eclipse.ltk.core.refactoring.CompositeChange ltkChange = new org.eclipse.ltk.core.refactoring.CompositeChange(
                compositeChange.getName());
        for (Change child : compositeChange.getChildren()) {
            ltkChange.add(toLTK(child));
        }
        return ltkChange;
    }

    /**
     * @return the Editor specific {@link Image} to given {@link CorrectionImage} identifier.
     */
    public static Image toLTK(final CorrectionImage imageId) {
        if (imageId != null) {
            return ExecutionUtils.runObjectUI(new RunnableObjectEx<Image>() {
                @Override
                public Image runObject() throws Exception {
                    switch (imageId) {
                    case IMG_CORRECTION_CHANGE:
                        return DartPluginImages.get(DartPluginImages.IMG_CORRECTION_CHANGE);
                    case IMG_CORRECTION_CLASS:
                        return DartPluginImages.get(DartPluginImages.IMG_OBJS_CLASS);
                    }
                    return null;
                }
            });
        }
        return null;
    }

    /**
     * @return the LTK change for the given Services {@link CompositeChange}.
     */
    public static org.eclipse.ltk.core.refactoring.Change toLTK(MergeCompositeChange mergeChange) {
        String mergedName = mergeChange.getName();
        CompositeChange pChange = mergeChange.getPreviewChange();
        CompositeChange eChange = mergeChange.getExecuteChange();
        final org.eclipse.ltk.core.refactoring.CompositeChange previewChange = toLTK(pChange);
        final org.eclipse.ltk.core.refactoring.CompositeChange executeChange = toLTK(eChange);
        // May be no preview changes, for example because all these changes are applied to external
        // files (in the Pub cache) and we ignored them.
        if (previewChange.getChildren().length == 0) {
            return getRenamedChange(mergedName, executeChange);
        }
        // OK, create wrapper LTK CompositeChange
        return new org.eclipse.ltk.core.refactoring.CompositeChange(mergedName,
                new org.eclipse.ltk.core.refactoring.Change[] { previewChange, executeChange }) {
            @Override
            public org.eclipse.ltk.core.refactoring.Change perform(IProgressMonitor pm) throws CoreException {
                mergeTextChanges(executeChange, previewChange);
                return executeChange.perform(pm);
            }
        };
    }

    /**
     * @return the LTK status for the given Services {@link RefactoringStatus}.
     */
    public static org.eclipse.ltk.core.refactoring.RefactoringStatus toLTK(RefactoringStatus status) {
        org.eclipse.ltk.core.refactoring.RefactoringStatus result = new org.eclipse.ltk.core.refactoring.RefactoringStatus();
        for (RefactoringStatusEntry entry : status.getEntries()) {
            result.addEntry(toLTK(entry.getSeverity()), entry.getMessage(), toLTK(entry.getContext()), null,
                    org.eclipse.ltk.core.refactoring.RefactoringStatusEntry.NO_CODE);
        }
        return result;
    }

    /**
     * @return the Dart status context for the given Services {@link RefactoringStatusContext}.
     */
    public static org.eclipse.ltk.core.refactoring.RefactoringStatusContext toLTK(
            RefactoringStatusContext context) {
        if (context == null) {
            return null;
        }
        return new DartStatusContext_OLD(context.getContext(), context.getSource(), context.getRange());
    }

    /**
     * @return the LTK {@link TextFileChange} for the given services {@link SourceChange}.
     */
    public static TextFileChange toLTK(SourceChange change) {
        Source source = change.getSource();
        // prepare IFile
        IFile file = getFile(source);
        if (file == null) {
            return null;
        }
        // prepare CompilationUnitChange
        CompilationUnitChange ltkChange = new CompilationUnitChange(change.getName(), file);
        ltkChange.setEdit(new MultiTextEdit());
        Map<String, List<Edit>> editGroups = change.getEditGroups();
        for (Entry<String, List<Edit>> entry : editGroups.entrySet()) {
            List<Edit> edits = entry.getValue();
            // add edits
            TextEdit ltkEdits[] = toLTK(edits);
            try {
                for (TextEdit ltkEdit : ltkEdits) {
                    ltkChange.addEdit(ltkEdit);
                }
            } catch (MalformedTreeException e) {
                throw new Error(source + " " + StringUtils.join(ltkEdits, " "), e);
            }
            // add group
            String groupName = entry.getKey();
            if (StringUtils.isNotEmpty(groupName)) {
                ltkChange.addTextEditGroup(new TextEditGroup(groupName, ltkEdits));
            }
        }
        return ltkChange;
    }

    /**
     * @return the error status for given {@link Throwable}.
     */
    public static org.eclipse.ltk.core.refactoring.RefactoringStatus toLTK(Throwable e) {
        IStatus status = createRuntimeStatus(e);
        return org.eclipse.ltk.core.refactoring.RefactoringStatus.create(status);
    }

    /**
     * @return the {@link IDartCompletionProposal} for the given {@link CreateFileCorrectionProposal}.
     */
    public static IDartCompletionProposal toUI(AddDependencyCorrectionProposal proposal) {
        return new com.google.dart.tools.ui.internal.text.correction.proposals.AddDependencyCorrectionProposal(
                proposal.getKind().getRelevance(), proposal.getName(), proposal.getFile(),
                proposal.getPackageName());
    }

    /**
     * @return the Eclipse {@link ICompletionProposal} for the given {@link CorrectionProposal}.
     */
    public static ICompletionProposal toUI(CorrectionProposal serviceProposal) {
        if (serviceProposal instanceof ChangeCorrectionProposal) {
            ChangeCorrectionProposal changeProposal = (ChangeCorrectionProposal) serviceProposal;
            org.eclipse.ltk.core.refactoring.Change ltkChange = toLTK(changeProposal.getChange());
            if (ltkChange == null) {
                return null;
            }
            return new com.google.dart.tools.ui.internal.text.correction.proposals.ChangeCorrectionProposal(
                    changeProposal.getName(), ltkChange, changeProposal.getKind().getRelevance(),
                    toLTK(changeProposal.getKind().getImage()));
        }
        if (serviceProposal instanceof CreateFileCorrectionProposal) {
            CreateFileCorrectionProposal fileProposal = (CreateFileCorrectionProposal) serviceProposal;
            return toUI(fileProposal);
        }
        if (serviceProposal instanceof AddDependencyCorrectionProposal) {
            AddDependencyCorrectionProposal proposal = (AddDependencyCorrectionProposal) serviceProposal;
            return toUI(proposal);
        }
        if (serviceProposal instanceof SourceCorrectionProposal) {
            SourceCorrectionProposal sourceProposal = (SourceCorrectionProposal) serviceProposal;
            return toUI(sourceProposal);
        }
        return null;
    }

    /**
     * @return the {@link IDartCompletionProposal} for the given {@link CreateFileCorrectionProposal}.
     */
    public static IDartCompletionProposal toUI(CreateFileCorrectionProposal fileProposal) {
        return new com.google.dart.tools.ui.internal.text.correction.proposals.CreateFileCorrectionProposal(
                fileProposal.getKind().getRelevance(), fileProposal.getName(), fileProposal.getFile(),
                fileProposal.getContent());
    }

    /**
     * @return the {@link LinkedCorrectionProposal_OLD} for the given {@link SourceCorrectionProposal}.
     */
    public static LinkedCorrectionProposal_OLD toUI(SourceCorrectionProposal sourceProposal) {
        // prepare TextChange
        SourceChange sourceChange = sourceProposal.getChange();
        TextChange textChange = ServiceUtils_OLD.toLTK(sourceChange);
        if (textChange == null) {
            return null;
        }
        // prepare UI proposal
        CorrectionKind kind = sourceProposal.getKind();
        Image image = ServiceUtils_OLD.toLTK(kind.getImage());
        LinkedCorrectionProposal_OLD uiProposal = new LinkedCorrectionProposal_OLD(sourceProposal.getName(),
                sourceChange.getSource(), textChange, kind.getRelevance(), image);
        // add linked positions
        for (Entry<String, List<SourceRange>> entry : sourceProposal.getLinkedPositions().entrySet()) {
            String group = entry.getKey();
            for (SourceRange position : entry.getValue()) {
                uiProposal.addLinkedPosition(TrackedPositions.forRange(position), false, group);
            }
        }
        // add proposals
        for (Entry<String, List<LinkedPositionProposal>> entry : sourceProposal.getLinkedPositionProposals()
                .entrySet()) {
            String group = entry.getKey();
            for (LinkedPositionProposal proposal : entry.getValue()) {
                uiProposal.addLinkedPositionProposal(group, proposal.getText(), toLTK(proposal.getIcon()));
            }
        }
        // set end position
        {
            SourceRange endRange = sourceProposal.getEndRange();
            if (endRange != null) {
                uiProposal.setEndPosition(TrackedPositions.forRange(endRange));
            }
        }
        // done
        return uiProposal;
    }

    /**
     * @return the error {@link IStatus} for the given {@link Throwable}.
     */
    private static IStatus createRuntimeStatus(Throwable e) {
        return new Status(IStatus.ERROR, DartToolsPlugin.getPluginId(), e.getMessage(), e);
    }

    /**
     * @return the {@link IFile} of the given {@link Source}, may be {@code null} if external.
     */
    private static IFile getFile(Source source) {
        return (IFile) DartCore.getProjectManager().getResource(source);
    }

    private static org.eclipse.ltk.core.refactoring.CompositeChange getRenamedChange(String newName,
            final org.eclipse.ltk.core.refactoring.CompositeChange executeChange) {
        org.eclipse.ltk.core.refactoring.CompositeChange renamedExecuteChange;
        renamedExecuteChange = new org.eclipse.ltk.core.refactoring.CompositeChange(newName);
        renamedExecuteChange.merge(executeChange);
        return renamedExecuteChange;
    }

    /**
     * Merges {@link TextChange}s from "newCompositeChange" into "existingCompositeChange".
     */
    private static void mergeTextChanges(org.eclipse.ltk.core.refactoring.CompositeChange existingCompositeChange,
            org.eclipse.ltk.core.refactoring.CompositeChange newCompositeChange) {
        // [element -> Change map] in CompositeChange
        Map<Object, org.eclipse.ltk.core.refactoring.Change> elementChanges = Maps.newHashMap();
        for (org.eclipse.ltk.core.refactoring.Change change : existingCompositeChange.getChildren()) {
            Object modifiedElement = change.getModifiedElement();
            elementChanges.put(modifiedElement, change);
        }
        // merge new changes into CompositeChange
        for (org.eclipse.ltk.core.refactoring.Change newChange : newCompositeChange.getChildren()) {
            // ignore if disabled (in preview UI)
            if (!newChange.isEnabled()) {
                continue;
            }
            // prepare existing TextChange
            Object modifiedElement = newChange.getModifiedElement();
            org.eclipse.ltk.core.refactoring.Change existingChange = elementChanges.get(modifiedElement);
            // add TextEditChangeGroup from new TextChange
            if (existingChange instanceof TextChange && newChange instanceof TextChange) {
                TextChange existingTextChange = (TextChange) existingChange;
                TextEdit existingTextEdit = existingTextChange.getEdit();
                TextChange newTextChange = (TextChange) newChange;
                // remember TextEdit(s) disabled in preview UI
                Set<TextEdit> disabledTextEdits = Sets.newHashSet();
                for (TextEditChangeGroup group : newTextChange.getTextEditChangeGroups()) {
                    if (!group.isEnabled()) {
                        Collections.addAll(disabledTextEdits, group.getTextEdits());
                    }
                }
                // merge not disabled TextEdit(s)
                TextEdit newTextEdit = newTextChange.getEdit();
                if (newTextEdit != null) {
                    for (TextEdit childTextEdit : newTextEdit.getChildren()) {
                        if (disabledTextEdits.contains(childTextEdit)) {
                            continue;
                        }
                        childTextEdit.getParent().removeChild(childTextEdit);
                        TextChangeCompatibility.insert(existingTextEdit, childTextEdit);
                    }
                }
            } else {
                newCompositeChange.remove(newChange);
                existingCompositeChange.add(newChange);
            }
        }
    }

    private static TextEdit toLTK(Edit edit) {
        return new ReplaceEdit(edit.getOffset(), edit.getLength(), edit.getReplacement());
    }

    private static TextEdit[] toLTK(List<Edit> edits) {
        // NB(scheglov) It is a bad idea to ensure uniqueness of Edit(s) here.
        List<TextEdit> ltkEdits = Lists.newArrayList();
        for (Edit edit : edits) {
            TextEdit ltkEdit = toLTK(edit);
            ltkEdits.add(ltkEdit);
        }
        return ltkEdits.toArray(new TextEdit[ltkEdits.size()]);
    }

    /**
     * @return the LTK status severity for the given Service {@link RefactoringStatusSeverity}.
     */
    private static int toLTK(RefactoringStatusSeverity severity) {
        switch (severity) {
        case OK:
            return org.eclipse.ltk.core.refactoring.RefactoringStatus.OK;
        case INFO:
            return org.eclipse.ltk.core.refactoring.RefactoringStatus.INFO;
        case WARNING:
            return org.eclipse.ltk.core.refactoring.RefactoringStatus.WARNING;
        case ERROR:
            return org.eclipse.ltk.core.refactoring.RefactoringStatus.ERROR;
        case FATAL:
            return org.eclipse.ltk.core.refactoring.RefactoringStatus.FATAL;
        default:
            throw new IllegalArgumentException("severity: " + severity);
        }
    }
}