public static List<? extends PsiElement> resolveSimpleReference( PsiElement scopeElement, String name) { final List<DartComponentName> result = new ArrayList<DartComponentName>(); // local final ResolveScopeProcessor resolveScopeProcessor = new ResolveScopeProcessor(result, name, DartResolveUtil.isLValue(scopeElement)); PsiTreeUtil.treeWalkUp(resolveScopeProcessor, scopeElement, null, new ResolveState()); // supers final DartClass dartClass = PsiTreeUtil.getParentOfType(scopeElement, DartClass.class); final boolean inClass = PsiTreeUtil.getParentOfType(scopeElement, DartClassBody.class, false) != null; if (result.isEmpty() && dartClass != null && inClass) { final DartComponent field = filterAccess(scopeElement, dartClass.findMembersByName(name)); if (field != null) { return toResult(field.getComponentName()); } } // global if (result.isEmpty()) { final List<VirtualFile> libraryFiles = DartResolveUtil.findLibrary(scopeElement.getContainingFile()); DartResolveUtil.processTopLevelDeclarations( scopeElement, resolveScopeProcessor, libraryFiles, name); } // dart:core if (result.isEmpty() && !"void".equals(name)) { final List<VirtualFile> libraryFiles = DartLibraryIndex.findLibraryClass(scopeElement, "dart:core"); DartResolveUtil.processTopLevelDeclarations( scopeElement, resolveScopeProcessor, libraryFiles, name); } return result; }
@NotNull @Override public ResolveResult[] multiResolve(boolean incompleteCode) { final String libraryName = getText(); final List<VirtualFile> libFiles = DartResolveUtil.findLibraryByName(this, libraryName); if (libFiles.isEmpty()) return ResolveResult.EMPTY_ARRAY; final List<ResolveResult> result = new SmartList<ResolveResult>(); for (VirtualFile libFile : libFiles) { final PsiFile psiFile = getManager().findFile(libFile); for (PsiElement root : DartResolveUtil.findDartRoots(psiFile)) { final DartLibraryStatement libraryStatement = PsiTreeUtil.getChildOfType(root, DartLibraryStatement.class); final DartLibraryNameElement libraryNameElement = libraryStatement == null ? null : libraryStatement.getLibraryNameElement(); if (libraryNameElement != null) { result.add(new PsiElementResolveResult(libraryNameElement)); } } } return result.toArray(new ResolveResult[result.size()]); }
@Nullable @Override public List<? extends PsiElement> resolve( @NotNull DartReference reference, boolean incompleteCode) { if (reference instanceof DartThisExpression) { return toResult(PsiTreeUtil.getParentOfType(reference, DartClass.class)); } if (reference instanceof DartParameterNameReferenceExpression) { final DartCallExpression callExpression = PsiTreeUtil.getParentOfType(reference, DartCallExpression.class); final DartExpression expression = callExpression != null ? callExpression.getExpression() : null; final PsiElement target = expression instanceof DartReference ? ((DartReference) expression).resolve() : null; final DartFormalParameterList parameters = PsiTreeUtil.getChildOfType( target != null ? target.getParent() : null, DartFormalParameterList.class); return toResult(DartResolveUtil.findParameterByName(parameters, reference.getText())); } if (DartResolveUtil.aloneOrFirstInChain(reference)) { return resolveSimpleReference(reference); } final DartReference leftReference = DartResolveUtil.getLeftReference(reference); // reference [node, node] final DartReference[] references = PsiTreeUtil.getChildrenOfType(reference, DartReference.class); if (references != null && references.length == 2) { // prefix final List<DartComponentName> names = DartResolveUtil.findComponentsInLibraryByPrefix( reference, references[0].getCanonicalText(), references[1].getCanonicalText()); if (!names.isEmpty()) { return toResult(names); } return toResult(references[1].resolve()); } else if (leftReference != null) { final DartClassResolveResult classResolveResult = leftReference.resolveDartClass(); final DartClass dartClass = classResolveResult.getDartClass(); if (dartClass != null) { final String name = reference.getCanonicalText(); final DartComponent subComponent = leftReference instanceof DartType ? dartClass.findNamedConstructor(name) : filterAccess(reference, dartClass.findMembersByName(name)); return toResult(subComponent == null ? null : subComponent.getComponentName()); } // prefix final List<DartComponentName> names = DartResolveUtil.findComponentsInLibraryByPrefix( reference, leftReference.getCanonicalText(), reference.getCanonicalText()); if (!names.isEmpty()) { return toResult(names); } } return null; }
@Nullable private static DartComponent filterAccess(PsiElement element, List<DartComponent> components) { final boolean lValue = DartResolveUtil.isLValue(element); return ContainerUtil.find( components, new Condition<DartComponent>() { @Override public boolean value(DartComponent component) { if (lValue && component.isSetter()) { return true; } else if (!lValue && component.isGetter()) { return true; } boolean isGetterOrSetter = component.isSetter() || component.isGetter(); return !isGetterOrSetter; } }); }
@Override public void updateParameterInfo(@NotNull PsiElement place, UpdateParameterInfoContext context) { int parameterIndex = DartResolveUtil.getArgumentIndex(place); context.setCurrentParameter(parameterIndex); if (context.getParameterOwner() == null) { context.setParameterOwner(place); } else if (context.getParameterOwner() != PsiTreeUtil.getParentOfType(place, DartCallExpression.class, DartNewExpression.class)) { context.removeHint(); return; } final Object[] objects = context.getObjectsToView(); for (int i = 0; i < objects.length; i++) { context.setUIComponentEnabled(i, true); } }
public static String generateDoc(final PsiElement element) { if (!(element instanceof DartComponent) && !(element.getParent() instanceof DartComponent)) { return null; } final DartComponent namedComponent = (DartComponent) (element instanceof DartComponent ? element : element.getParent()); final String signatureHtml; { final StringBuilder builder = new StringBuilder(); appendSignature(namedComponent, builder); signatureHtml = builder.toString(); } final String containingLibraryName; final PsiFile file = element.getContainingFile(); if (file != null) { containingLibraryName = DartResolveUtil.getLibraryName(file); } else { containingLibraryName = null; } final String containingClassDescription; final DartClass dartClass = PsiTreeUtil.getParentOfType(namedComponent, DartClass.class); if (dartClass != null) { final StringBuilder builder = new StringBuilder(); builder.append(dartClass.getName()); appendTypeParams(builder, dartClass.getTypeParameters()); containingClassDescription = builder.toString(); } else { containingClassDescription = null; } final String docText = getDocumentationText(namedComponent); return generateDoc( signatureHtml, true, docText, containingLibraryName, containingClassDescription, null, null); }
@NotNull @Override public Collection<StructureViewTreeElement> getChildrenBase() { final NavigatablePsiElement element = getElement(); final List<StructureViewTreeElement> result = new ArrayList<StructureViewTreeElement>(); if (element instanceof DartFile || element instanceof DartEmbeddedContent) { THashSet<DartComponentName> componentNames = new THashSet<DartComponentName>(); DartPsiCompositeElementImpl.processDeclarationsImpl( element, new ComponentNameScopeProcessor(componentNames), ResolveState.initial(), null); for (DartComponentName componentName : componentNames) { PsiElement parent = componentName.getParent(); if (parent instanceof DartComponent) { result.add(new DartStructureViewElement((DartComponent) parent)); } } } else if (element instanceof DartClass) { for (DartComponent subNamedComponent : DartResolveUtil.getNamedSubComponents((DartClass) element)) { result.add(new DartStructureViewElement(subNamedComponent)); } } Collections.sort( result, new Comparator<StructureViewTreeElement>() { @Override public int compare(StructureViewTreeElement o1, StructureViewTreeElement o2) { PsiElement element1, element2; if (o1 instanceof DartStructureViewElement && o2 instanceof DartStructureViewElement && (element1 = ((DartStructureViewElement) o1).getElement()) != null && (element2 = ((DartStructureViewElement) o2).getElement()) != null) { return element1.getTextRange().getStartOffset() - element2.getTextRange().getStartOffset(); } return 0; } }); return result; }
@Override public void showParameterInfo(@NotNull PsiElement element, CreateParameterInfoContext context) { DartFunctionDescription functionDescription = null; if (element instanceof DartCallExpression) { functionDescription = DartFunctionDescription.tryGetDescription((DartCallExpression) element); } else if (element instanceof DartNewExpression) { final DartNewExpression newExpression = (DartNewExpression) element; final DartType type = newExpression.getType(); final DartClassResolveResult classResolveResult = DartResolveUtil.resolveClassByType(type); PsiElement psiElement = ((DartNewExpression) element).getReferenceExpression(); psiElement = psiElement == null && type != null ? type.getReferenceExpression() : psiElement; final PsiElement target = psiElement != null ? ((DartReference) psiElement).resolve() : null; if (target instanceof DartComponentName) { functionDescription = DartFunctionDescription.createDescription( (DartComponent) target.getParent(), classResolveResult); } } if (functionDescription != null && functionDescription.getParameters().length > 0) { context.setItemsToShow(new Object[] {functionDescription}); context.showHint(element, element.getTextRange().getStartOffset(), this); } }
@Override public void actionPerformed(final AnActionEvent e) { final PsiFile psiFile = LangDataKeys.PSI_FILE.getData(e.getDataContext()); if (!(psiFile instanceof DartFile)) { return; } final VirtualFile virtualFile = DartResolveUtil.getRealVirtualFile(psiFile); if (virtualFile == null) { return; } final DartSettings settings = DartSettingsUtil.getSettings(); final VirtualFile dart2js = settings.getDart2JS(); if (dart2js == null) { Messages.showOkCancelDialog( e.getProject(), DartBundle.message("dart.sdk.bad.dart2js.path", settings.getDart2JSUrl()), DartBundle.message("dart.warning"), icons.DartIcons.Dart_16); return; } final String jsFilePath = virtualFile.getPath() + ".js"; final Dart2JSSettingsDialog dialog = new Dart2JSSettingsDialog(psiFile.getProject(), jsFilePath); dialog.show(); if (!dialog.isOK()) { return; } new Task.Backgroundable(psiFile.getProject(), "dart2js", true) { public void run(@NotNull ProgressIndicator indicator) { indicator.setText("Running dart2js..."); indicator.setFraction(0.0); final GeneralCommandLine command = new GeneralCommandLine(); command.setExePath(dart2js.getPath()); if (dialog.isCheckedMode()) { command.addParameter("--checked"); } if (dialog.isMinify()) { command.addParameter("--minify"); } command.addParameter("--out=" + dialog.getOutputPath()); command.addParameter(virtualFile.getPath()); // save on disk ApplicationManager.getApplication() .invokeAndWait( new Runnable() { @Override public void run() { FileDocumentManager.getInstance().saveAllDocuments(); } }, ModalityState.defaultModalityState()); try { final String output = ScriptRunnerUtil.getProcessOutput(command); ProgressManager.progress(""); LOG.debug(output); boolean error = !output.isEmpty(); if (error) { Notifications.Bus.notify( new Notification( e.getPresentation().getText(), DartBundle.message("dart2js.title"), DartBundle.message("dart2js.js.file.creation.error", output), NotificationType.ERROR)); return; } Notifications.Bus.notify( new Notification( e.getPresentation().getText(), DartBundle.message("dart2js.title"), DartBundle.message("dart2js.js.file.created", jsFilePath), NotificationType.INFORMATION)); final String parentDir = VfsUtil.getParentDir(dialog.getOutputPath()); assert parentDir != null; final VirtualFile outputParentVirtualFile = VirtualFileManager.getInstance().findFileByUrl(VfsUtilCore.pathToUrl(parentDir)); if (outputParentVirtualFile != null) { outputParentVirtualFile.refresh(true, false); } } catch (ExecutionException ex) { LOG.error(ex); Notifications.Bus.notify( new Notification( e.getPresentation().getText(), DartBundle.message("dart2js.title"), DartBundle.message("dart2js.js.file.creation.error", ex.getMessage()), NotificationType.ERROR)); } indicator.setFraction(1.0); } }.setCancelText("Stop").queue(); }