/******************************************************************************* * Copyright (c) 2008, 2017 xored software, Inc. and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * xored software, Inc. - initial API and Implementation (Alex Panchenko) *******************************************************************************/ package org.eclipse.dltk.tcl.internal.ui.text; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.dltk.compiler.problem.DefaultProblemIdentifier; import org.eclipse.dltk.compiler.problem.IProblemIdentifier; import org.eclipse.dltk.core.CorrectionEngine; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.DLTKLanguageManager; import org.eclipse.dltk.core.IDLTKLanguageToolkit; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.launching.IInterpreterInstall; import org.eclipse.dltk.launching.ScriptRuntime; import org.eclipse.dltk.tcl.core.TclNature; import org.eclipse.dltk.tcl.core.TclPackagesManager; import org.eclipse.dltk.tcl.core.TclProblems; import org.eclipse.dltk.tcl.core.packages.TclPackageInfo; import org.eclipse.dltk.tcl.internal.core.packages.TclVariableResolver; import org.eclipse.dltk.ui.editor.IScriptAnnotation; import org.eclipse.dltk.ui.text.AnnotationResolutionProposal; import org.eclipse.dltk.ui.text.IScriptCorrectionContext; import org.eclipse.dltk.ui.text.IScriptCorrectionProcessor; import org.eclipse.dltk.ui.text.MarkerResolutionProposal; public class TclSourcePackageCorrectionProcessor implements IScriptCorrectionProcessor { @Override public boolean canFix(IScriptAnnotation annotation) { return isFixable(annotation); } public static boolean isFixable(IScriptAnnotation annotation) { if (annotation.getId() == TclProblems.UNKNOWN_REQUIRED_PACKAGE) { final String[] args = annotation.getArguments(); if (args != null && args.length != 0 && args[0] != null) { final ISourceModule module = annotation.getSourceModule(); if (module != null) { final IScriptProject project = module.getScriptProject(); if (project != null) { if (isFixable(args[0], project)) { return true; } } } } } else if (annotation .getId() == TclProblems.UNKNOWN_REQUIRED_PACKAGE_CORRECTION) { return true; } else if (annotation .getId() == TclProblems.UNKNOWN_SOURCE_CORRECTION) { return true; } else if (annotation.getId() == TclProblems.UNKNOWN_SOURCE) { final String[] args = annotation.getArguments(); if (args != null && args.length != 0 && args[0] != null) { final ISourceModule module = annotation.getSourceModule(); if (module != null) { final IScriptProject project = module.getScriptProject(); if (project != null) { if (TclSourceMarkerResolution.fixAvailable(module, args[0])) { return true; } } } } } return false; } @Override public void computeQuickAssistProposals(IScriptAnnotation annotation, IScriptCorrectionContext context) { if (annotation.getId() == TclProblems.UNKNOWN_REQUIRED_PACKAGE) { if (isFixable(annotation)) { final String pkgName = annotation.getArguments()[0]; if (addPackageName(context, pkgName)) { context.addProposal( new AnnotationResolutionProposal( new TclRequirePackageMarkerResolution( pkgName, context.getProject()), annotation)); } } } else if (annotation .getId() == TclProblems.UNKNOWN_REQUIRED_PACKAGE_CORRECTION) { final String pkgName = annotation.getArguments()[0]; if (addPackageName(context, pkgName)) { context.addProposal(new AnnotationResolutionProposal( new TclRequirePackageCorrectionMarkerResolution(pkgName, context.getProject(), context.getModule()), annotation)); addGlobalVariableProposals(annotation, context, pkgName); } } else if (annotation .getId() == TclProblems.UNKNOWN_SOURCE_CORRECTION) { final String fName = annotation.getArguments()[0]; if (addSourceFile(context, fName)) { context.addProposal(new AnnotationResolutionProposal( new TclSourceCorrectionMarkerResolution(fName, context.getProject(), context.getModule()), annotation)); addGlobalVariableProposals(annotation, context, fName); } } else if (annotation.getId() == TclProblems.UNKNOWN_SOURCE) { final String fName = annotation.getArguments()[0]; if (addSourceFile(context, fName)) { if (TclSourceMarkerResolution.fixAvailable(context.getModule(), fName)) { context.addProposal(new AnnotationResolutionProposal( new TclSourceMarkerResolution(fName, context.getProject(), context.getModule()), annotation)); } } } } private void addGlobalVariableProposals(IScriptAnnotation annotation, IScriptCorrectionContext context, final String fName) { String[] names = TclVariableResolver.extractVariableNames(fName); Map<String, String> eMap = TclPackagesManager .getVariables(context.getProject().getElementName()); if (names != null) { for (String var : names) { if (!eMap.containsKey(var)) { context.addProposal(new AnnotationResolutionProposal( new TclGlobalVariableSourceCorrectionMarkerResolution( var, context.getProject()), annotation)); } } } } private static final String PACKAGES = TclSourcePackageCorrectionProcessor.class .getName() + "#PACKAGES"; //$NON-NLS-1$ private static final String SOURCES = TclSourcePackageCorrectionProcessor.class .getName() + "#SOURCES"; //$NON-NLS-1$ private boolean addPackageName(IScriptCorrectionContext context, String pkgName) { return addAttributeValue(context, PACKAGES, pkgName); } private boolean addSourceFile(IScriptCorrectionContext context, String source) { return addAttributeValue(context, SOURCES, source); } private boolean addAttributeValue(IScriptCorrectionContext context, final String attribute, String value) { @SuppressWarnings("unchecked") Set<String> values = (Set<String>) context.getAttribute(attribute); if (values != null) { return values.add(value); } else { values = new HashSet<>(); values.add(value); context.setAttribute(attribute, values); return true; } } @Override public boolean canFix(IMarker marker) { return isFixable(marker); } public static boolean isFixable(IMarker marker) { IProblemIdentifier idValue = DefaultProblemIdentifier .getProblemId(marker); if (idValue == TclProblems.UNKNOWN_REQUIRED_PACKAGE) { final String[] args = CorrectionEngine.getProblemArguments(marker); if (args != null && args.length != 0 && args[0] != null) { IResource resource = marker.getResource(); IProject project = resource.getProject(); IScriptProject scriptProject = DLTKCore.create(project); if (isFixable(args[0], scriptProject)) { return true; } } } else if (idValue == TclProblems.UNKNOWN_REQUIRED_PACKAGE_CORRECTION) { return true; } else if (idValue == TclProblems.UNKNOWN_SOURCE_CORRECTION) { return true; } else if (idValue == TclProblems.UNKNOWN_SOURCE) { final String[] args = CorrectionEngine.getProblemArguments(marker); if (args != null && args.length != 0 && args[0] != null) { IResource resource = marker.getResource(); if (TclSourceMarkerResolution.fixAvailable( (ISourceModule) DLTKCore.create(resource), args[0])) { return true; } } } return false; } @Override public void computeQuickAssistProposals(IMarker marker, IScriptCorrectionContext context) { IProblemIdentifier idValue = DefaultProblemIdentifier .getProblemId(marker); if (idValue == TclProblems.UNKNOWN_REQUIRED_PACKAGE) { if (isFixable(marker)) { final String pkgName = CorrectionEngine .getProblemArguments(marker)[0]; if (addPackageName(context, pkgName)) { context.addProposal( new MarkerResolutionProposal( new TclRequirePackageMarkerResolution( pkgName, context.getProject()), marker)); } } } else if (idValue == TclProblems.UNKNOWN_REQUIRED_PACKAGE_CORRECTION) { final String pkgName = CorrectionEngine .getProblemArguments(marker)[0]; if (addPackageName(context, pkgName)) { context.addProposal(new MarkerResolutionProposal( new TclRequirePackageCorrectionMarkerResolution(pkgName, context.getProject(), context.getModule()), marker)); addGlobalVariablesProposals(marker, context, pkgName); } addGlobalVariablesProposals(marker, context, pkgName); } else if (idValue == TclProblems.UNKNOWN_SOURCE_CORRECTION) { final String fName = CorrectionEngine .getProblemArguments(marker)[0]; context.addProposal(new MarkerResolutionProposal( new TclSourceCorrectionMarkerResolution(fName, context.getProject(), context.getModule()), marker)); } else if (idValue == TclProblems.UNKNOWN_SOURCE) { final String fName = CorrectionEngine .getProblemArguments(marker)[0]; if (TclSourceMarkerResolution.fixAvailable(context.getModule(), fName)) { context.addProposal(new MarkerResolutionProposal( new TclSourceMarkerResolution(fName, context.getProject(), context.getModule()), marker)); } } } private void addGlobalVariablesProposals(IMarker marker, IScriptCorrectionContext context, final String pkgName) { String[] names = TclVariableResolver.extractVariableNames(pkgName); Map<String, String> eMap = TclPackagesManager .getVariables(context.getProject().getElementName()); if (names != null) { for (String var : names) { if (!eMap.containsKey(var)) { context.addProposal(new MarkerResolutionProposal( new TclGlobalVariableSourceCorrectionMarkerResolution( var, context.getProject()), marker)); } } } } public static boolean isFixable(String pkgName, IScriptProject scriptProject) { IDLTKLanguageToolkit toolkit = null; toolkit = DLTKLanguageManager.getLanguageToolkit(scriptProject); if (toolkit != null && toolkit.getNatureId().equals(TclNature.NATURE_ID)) { IInterpreterInstall install = null; try { install = ScriptRuntime.getInterpreterInstall(scriptProject); } catch (CoreException e) { if (DLTKCore.DEBUG) { e.printStackTrace(); } } if (install != null) { TclPackageInfo info = TclPackagesManager.getPackageInfo(install, pkgName, true); if (info == null || !info.isFetched()) { return false; } return true; } } return false; } }