/* * Copyright 2000-2006 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0 * * 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.intellij.lang.javascript.inspections.actionscript; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.MacroCallNode; import com.intellij.codeInsight.template.macro.MacroFactory; import com.intellij.codeInspection.*; import com.intellij.lang.ASTNode; import com.intellij.lang.javascript.DialectDetector; import com.intellij.lang.javascript.JSTokenTypes; import com.intellij.lang.javascript.flex.FlexBundle; import com.intellij.lang.javascript.inspections.JSInspection; import com.intellij.lang.javascript.psi.*; import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils; import com.intellij.lang.javascript.types.TypeFromUsageDetector; import com.intellij.lang.javascript.validation.fixes.BaseCreateFix; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; /** * @author Maxim.Mossienko */ public class JSUntypedDeclarationInspection extends JSInspection { @NotNull public String getDisplayName() { return FlexBundle.message("js.untyped.declaration.inspection.name"); } @NotNull protected JSElementVisitor createVisitor(final ProblemsHolder holder, LocalInspectionToolSession session) { return new JSElementVisitor() { @Override public void visitJSVariable(final JSVariable node) { process(node, holder); } @Override public void visitJSFunctionExpression(final JSFunctionExpression node) { process(node, holder); } @Override public void visitJSFunctionDeclaration(final JSFunction node) { if (node.isConstructor() || node.isSetProperty()) return; process(node, holder); } }; } private static void process(final JSNamedElement node, final ProblemsHolder holder) { if (!DialectDetector.isActionScript(node)) return; ASTNode nameIdentifier = node.findNameIdentifier(); if ((nameIdentifier != null || node instanceof JSFunction) && JSPsiImplUtils.getTypeFromDeclaration(node) == null && (!(node instanceof JSParameter) || !((JSParameter)node).isRest()) ) { if (node instanceof JSFunctionExpression && nameIdentifier != null && PsiTreeUtil.getParentOfType(nameIdentifier.getPsi(), JSFunction.class) != node) { nameIdentifier = null; } LocalQuickFix[] fixes = holder.isOnTheFly() ? new LocalQuickFix[]{new AddTypeToDclFix()} : LocalQuickFix.EMPTY_ARRAY; holder.registerProblem( (nameIdentifier != null ? nameIdentifier:node.getNode().findChildByType(JSTokenTypes.FUNCTION_KEYWORD)).getPsi(), FlexBundle.message( node instanceof JSFunction ? "js.untyped.function.problem":"js.untyped.variable.problem", nameIdentifier != null ? nameIdentifier.getText():"anonymous" ), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fixes ); } } private static class AddTypeToDclFix implements LocalQuickFix { @NotNull public String getFamilyName() { return FlexBundle.message("js.untyped.declaration.problem.addtype.fix"); } public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { PsiElement anchor = descriptor.getPsiElement(); final PsiFile containingFile = anchor.getContainingFile(); PsiElement parent = anchor.getParent(); if (parent instanceof JSFunction) { anchor = ((JSFunction)parent).getParameterList(); } OpenFileDescriptor openDescriptor = new OpenFileDescriptor(project, containingFile.getVirtualFile(), anchor.getTextRange().getEndOffset()); openDescriptor.navigate(true); Editor textEditor = FileEditorManager.getInstance(project).getSelectedTextEditor(); TemplateManager templateManager = TemplateManager.getInstance(project); final Template t = templateManager.createTemplate("",""); t.addTextSegment(":"); JSType detectedTypeFromUsage = TypeFromUsageDetector.detectTypeFromUsage(parent, containingFile); if (detectedTypeFromUsage != null) { BaseCreateFix.addTypeVariable(t, "a", anchor, detectedTypeFromUsage.getTypeText(JSType.TypeTextFormat.CODE)); } else { String defaultValue = "uint"; if (ApplicationManager.getApplication().isUnitTestMode()) { t.addTextSegment(defaultValue); } else { t.addVariable("a", new MacroCallNode(MacroFactory.createMacro("complete")), new BaseCreateFix.MyExpression(defaultValue), true); } } templateManager.startTemplate(textEditor, t); } } }