Search in sources :

Example 26 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class RenderErrorContributor method reportRtlNotEnabled.

private void reportRtlNotEnabled(@NotNull RenderLogger logger, @Nullable RenderTask task) {
    ApplicationManager.getApplication().runReadAction(() -> {
        Project project = logger.getProject();
        if (project == null || project.isDisposed()) {
            return;
        }
        Module module = logger.getModule();
        if (module == null) {
            return;
        }
        AndroidFacet facet = AndroidFacet.getInstance(module);
        Manifest manifest = facet != null ? facet.getManifest() : null;
        Application application = manifest != null ? manifest.getApplication() : null;
        if (application == null) {
            return;
        }
        final XmlTag applicationTag = application.getXmlTag();
        if (applicationTag == null) {
            return;
        }
        HtmlBuilder builder = new HtmlBuilder();
        builder.add("(").addLink("Add android:supportsRtl=\"true\" to the manifest", logger.getLinkManager().createRunnableLink(() -> {
            new SetAttributeFix(project, applicationTag, AndroidManifest.ATTRIBUTE_SUPPORTS_RTL, ANDROID_URI, VALUE_TRUE).execute();
            EditorDesignSurface surface = task != null ? task.getDesignSurface() : null;
            if (surface != null) {
                surface.requestRender(true);
            }
        })).add(")");
        addIssue().setSeverity(HighlightSeverity.ERROR).setSummary("RTL support requires android:supportsRtl=\"true\" in the manifest").setHtmlContent(builder).build();
    });
}
Also used : Project(com.intellij.openapi.project.Project) EditorDesignSurface(com.android.tools.idea.ui.designer.EditorDesignSurface) HtmlBuilder(com.android.utils.HtmlBuilder) Module(com.intellij.openapi.module.Module) AndroidManifest(com.android.xml.AndroidManifest) Manifest(org.jetbrains.android.dom.manifest.Manifest) Application(org.jetbrains.android.dom.manifest.Application) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) XmlTag(com.intellij.psi.xml.XmlTag)

Example 27 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class RenderErrorContributor method reportOtherProblems.

private void reportOtherProblems(@NotNull RenderLogger logger, RenderTask task) {
    List<RenderProblem> messages = logger.getMessages();
    if (messages == null || messages.isEmpty()) {
        return;
    }
    Set<String> seenTags = Sets.newHashSet();
    for (RenderProblem message : messages) {
        String tag = message.getTag();
        if (tag != null && seenTags.contains(tag)) {
            continue;
        }
        seenTags.add(tag);
        if (tag != null) {
            if (LayoutLog.TAG_RESOURCES_FORMAT.equals(tag)) {
                reportTagResourceFormat(myResult, message);
                continue;
            } else if (LayoutLog.TAG_RTL_NOT_ENABLED.equals(tag)) {
                reportRtlNotEnabled(logger, task);
                continue;
            } else if (LayoutLog.TAG_RTL_NOT_SUPPORTED.equals(tag)) {
                addIssue().setSeverity(HighlightSeverity.ERROR).setSummary("RTL support requires API level >= 17").setHtmlContent(new HtmlBuilder().addHtml(message.getHtml())).build();
                continue;
            }
        }
        HtmlBuilder builder = new HtmlBuilder();
        String html = message.getHtml();
        Throwable throwable = message.getThrowable();
        String summary = "Render problem";
        if (throwable != null) {
            if (!reportSandboxError(throwable, false, true)) {
                if (reportThrowable(builder, throwable, !html.isEmpty() || !message.isDefaultHtml())) {
                    // The error was hidden.
                    if (!html.isEmpty()) {
                        builder.getStringBuilder().append(html);
                        builder.newlineIfNecessary();
                    }
                    summary = throwable.getLocalizedMessage() != null ? throwable.getLocalizedMessage() : summary;
                }
            } else {
                // This was processed as a Sandbox error
                continue;
            }
        } else {
            if (html.contains("has been edited more recently")) {
                summary = "Build out-of-date";
            }
            builder.getStringBuilder().append(html);
            builder.newlineIfNecessary();
        }
        addRefreshAction(builder);
        addIssue().setSeverity(HighlightSeverity.ERROR).setSummary(summary).setHtmlContent(builder).build();
    }
}
Also used : HtmlBuilder(com.android.utils.HtmlBuilder)

Example 28 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class RenderLogger method error.

@Override
public void error(@Nullable String tag, @Nullable String message, @Nullable Throwable throwable, @Nullable Object data) {
    String description = describe(message, throwable);
    if (LOG_ALL) {
        boolean token = RenderSecurityManager.enterSafeRegion(myCredential);
        try {
            LOG.warn(String.format("%1$s: %2$s", myName, description), throwable);
        } finally {
            RenderSecurityManager.exitSafeRegion(token);
        }
    }
    if (throwable != null) {
        if (throwable instanceof ClassNotFoundException) {
            // even mentioning that it is a class-not-found exception.)
            return;
        }
        if (checkForIssue164378(throwable)) {
            return;
        }
        if ("Unable to find the layout for Action Bar.".equals(description)) {
            description += "\nConsider updating to a more recent version of appcompat, or switch the rendering library in the IDE " + "down to API 21";
        }
        if (description.equals(throwable.getLocalizedMessage()) || description.equals(throwable.getMessage())) {
            description = "Exception raised during rendering: " + description;
        } else if (message == null) {
            // See if it looks like the known issue with CalendarView; if so, add a more intuitive message
            StackTraceElement[] stackTrace = throwable.getStackTrace();
            if (stackTrace.length >= 2 && stackTrace[0].getClassName().equals("android.text.format.DateUtils") && stackTrace[1].getClassName().equals("android.widget.CalendarView")) {
                RenderProblem.Html problem = RenderProblem.create(WARNING);
                problem.tag("59732");
                problem.throwable(throwable);
                HtmlBuilder builder = problem.getHtmlBuilder();
                builder.add("<CalendarView> and <DatePicker> are broken in this version of the rendering library. " + "Try updating your SDK in the SDK Manager when issue 59732 is fixed.");
                builder.add(" (");
                builder.addLink("Open Issue 59732", "http://b.android.com/59732");
                builder.add(", ");
                ShowExceptionFix detailsFix = new ShowExceptionFix(getModule().getProject(), throwable);
                builder.addLink("Show Exception", getLinkManager().createRunnableLink(detailsFix));
                builder.add(")");
                addMessage(problem);
                return;
            } else if (stackTrace.length >= 2 && stackTrace[0].getClassName().equals("android.support.v7.widget.RecyclerView") && stackTrace[0].getMethodName().equals("onMeasure") && stackTrace[1].getClassName().equals("android.view.View") && throwable.toString().equals("java.lang.NullPointerException")) {
                RenderProblem.Html problem = RenderProblem.create(WARNING);
                String issue = "72117";
                problem.tag(issue);
                problem.throwable(throwable);
                HtmlBuilder builder = problem.getHtmlBuilder();
                builder.add("The new RecyclerView does not yet work in Studio. We are working on a fix. ");
                // TODO: Add more specific error message here when we know where we are fixing it, e.g. either
                // to update their layoutlib (if we work around it there), or a new version of the recyclerview AAR.
                builder.add(" (");
                builder.addLink("Open Issue " + issue, "http://b.android.com/" + issue);
                builder.add(", ");
                ShowExceptionFix detailsFix = new ShowExceptionFix(myModule.getProject(), throwable);
                builder.addLink("Show Exception", getLinkManager().createRunnableLink(detailsFix));
                builder.add(")");
                addMessage(problem);
                return;
            }
        } else if (message.equals("onMeasure error") && throwable.toString().startsWith("java.lang.NoSuchMethodError: android.support.constraint.solver.widgets.Guideline.setRelative")) {
            RenderProblem.Html problem = RenderProblem.create(WARNING);
            String issue = "214853";
            problem.tag(issue);
            problem.throwable(throwable);
            HtmlBuilder builder = problem.getHtmlBuilder();
            builder.add("You appear to be using constraint layout version alpha3 or earlier; you must use version alpha4 or later " + "with this version of the layout editor (because the API for guidelines changed incompatibly as of alpha4.)");
            builder.add(" (");
            builder.addLink("Update Library", getLinkManager().createRunnableLink(() -> UpgradeConstraintLayoutFix.apply(myModule)));
            builder.add(", ");
            ShowExceptionFix detailsFix = new ShowExceptionFix(myModule.getProject(), throwable);
            builder.addLink("Show Exception", getLinkManager().createRunnableLink(detailsFix));
            builder.add(")");
            addMessage(problem);
            return;
        } else if (message.startsWith("Failed to configure parser for ") && message.endsWith(DOT_PNG)) {
            // See if it looks like a mismatched bitmap/color; if so, make a more intuitive error message
            StackTraceElement[] frames = throwable.getStackTrace();
            for (StackTraceElement frame : frames) {
                if (frame.getMethodName().equals("createFromXml") && frame.getClassName().equals("android.content.res.ColorStateList")) {
                    String path = message.substring("Failed to configure parser for ".length());
                    RenderProblem.Html problem = RenderProblem.create(WARNING);
                    problem.tag("bitmapAsColor");
                    // deliberately not setting the throwable on the problem: exception is misleading
                    HtmlBuilder builder = problem.getHtmlBuilder();
                    builder.add("Resource error: Attempted to load a bitmap as a color state list.").newline();
                    builder.add("Verify that your style/theme attributes are correct, and make sure layouts are using the right attributes.");
                    builder.newline().newline();
                    path = FileUtil.toSystemIndependentName(path);
                    String basePath = FileUtil.toSystemIndependentName(myModule.getProject().getBasePath());
                    if (path.startsWith(basePath)) {
                        path = path.substring(basePath.length());
                        if (path.startsWith(File.separator)) {
                            path = path.substring(File.separator.length());
                        }
                    }
                    path = FileUtil.toSystemDependentName(path);
                    builder.add("The relevant image is ").add(path);
                    Set<String> widgets = Sets.newHashSet();
                    for (StackTraceElement f : frames) {
                        if (f.getMethodName().equals(CONSTRUCTOR_NAME)) {
                            String className = f.getClassName();
                            if (className.startsWith(WIDGET_PKG_PREFIX)) {
                                widgets.add(className.substring(className.lastIndexOf('.') + 1));
                            }
                        }
                    }
                    if (!widgets.isEmpty()) {
                        List<String> sorted = Lists.newArrayList(widgets);
                        Collections.sort(sorted);
                        builder.newline().newline().add("Widgets possibly involved: ").add(Joiner.on(", ").join(sorted));
                    }
                    addMessage(problem);
                    return;
                } else if (frame.getClassName().startsWith("com.android.tools.")) {
                    break;
                }
            }
        } else if (message.startsWith("Failed to parse file ") && throwable instanceof XmlPullParserException) {
            XmlPullParserException e = (XmlPullParserException) throwable;
            String msg = e.getMessage();
            if (msg.startsWith("Binary XML file ")) {
                int index = msg.indexOf(':');
                if (index != -1 && index < msg.length() - 1) {
                    msg = msg.substring(index + 1).trim();
                }
            }
            int lineNumber = e.getLineNumber();
            int column = e.getColumnNumber();
            // Strip out useless input sources pointing back to the internal reader
            // e.g. "in java.io.InputStreamReader@4d957e26"
            String reader = " in java.io.InputStreamReader@";
            int index = msg.indexOf(reader);
            if (index != -1) {
                int end = msg.indexOf(')', index + 1);
                if (end != -1) {
                    msg = msg.substring(0, index) + msg.substring(end);
                }
            }
            String path = message.substring("Failed to parse file ".length());
            RenderProblem.Html problem = RenderProblem.create(WARNING);
            problem.tag("xmlParse");
            // Don't include exceptions for XML parser errors: that's just displaying irrelevant
            // information about how we ended up parsing the file
            //problem.throwable(throwable);
            HtmlBuilder builder = problem.getHtmlBuilder();
            if (lineNumber != -1) {
                builder.add("Line ").add(Integer.toString(lineNumber)).add(": ");
            }
            builder.add(msg);
            if (lineNumber != -1) {
                builder.add(" (");
                File file = new File(path);
                String url = HtmlLinkManager.createFilePositionUrl(file, lineNumber, column);
                if (url != null) {
                    builder.addLink("Show", url);
                    builder.add(")");
                }
            }
            addMessage(problem);
            return;
        }
        recordThrowable(throwable);
        myHaveExceptions = true;
    }
    addTag(tag);
    if (getProject() == null) {
        addMessage(RenderProblem.createPlain(ERROR, description).tag(tag).throwable(throwable));
    } else {
        addMessage(RenderProblem.createPlain(ERROR, description, getProject(), getLinkManager(), throwable).tag(tag));
    }
}
Also used : HashSet(com.intellij.util.containers.HashSet) HtmlBuilder(com.android.utils.HtmlBuilder) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) File(java.io.File)

Example 29 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class RenderProblem method createPlain.

@NotNull
public static RenderProblem createPlain(@NotNull HighlightSeverity severity, @NotNull String message, @NotNull Project project, @NotNull HtmlLinkManager linkManager, @Nullable Throwable throwable) {
    Html problem = new Html(severity, ourNextOrdinal++);
    HtmlBuilder builder = problem.getHtmlBuilder();
    builder.add(message);
    if (throwable != null) {
        String url = linkManager.createRunnableLink(new ShowExceptionFix(project, throwable));
        builder.add(" (").addLink("Details", url).add(")");
        problem.throwable(throwable);
        if (message.equals(throwable.getMessage())) {
            problem.myIsDefaultHtml = true;
        }
    }
    return problem;
}
Also used : HtmlBuilder(com.android.utils.HtmlBuilder) NotNull(org.jetbrains.annotations.NotNull)

Example 30 with HtmlBuilder

use of com.android.utils.HtmlBuilder in project android by JetBrains.

the class ViewLoader method checkModified.

/** Checks that the given class has not been edited since the last compilation (and if it has, logs a warning to the user) */
private void checkModified(@NotNull String fqcn) {
    if (DumbService.getInstance(myModule.getProject()).isDumb()) {
        // If the index is not ready, we can not check the modified time since it requires accessing the PSI
        return;
    }
    if (myModuleClassLoader != null && myModuleClassLoader.isSourceModified(fqcn, myCredential) && !myRecentlyModifiedClasses.contains(fqcn)) {
        assert myLogger != null;
        myRecentlyModifiedClasses.add(fqcn);
        RenderProblem.Html problem = RenderProblem.create(WARNING);
        HtmlBuilder builder = problem.getHtmlBuilder();
        String className = fqcn.substring(fqcn.lastIndexOf('.') + 1);
        builder.addLink("The " + className + " custom view has been edited more recently than the last build: ", "Build", " the project.", myLogger.getLinkManager().createBuildProjectUrl());
        myLogger.addMessage(problem);
    }
}
Also used : RenderProblem(com.android.tools.idea.rendering.RenderProblem) HtmlBuilder(com.android.utils.HtmlBuilder)

Aggregations

HtmlBuilder (com.android.utils.HtmlBuilder)36 NotNull (org.jetbrains.annotations.NotNull)9 XmlFile (com.intellij.psi.xml.XmlFile)8 Module (com.intellij.openapi.module.Module)7 Project (com.intellij.openapi.project.Project)7 File (java.io.File)6 IOException (java.io.IOException)3 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)3 VisibleForTesting (com.android.annotations.VisibleForTesting)2 SourceFile (com.android.ide.common.blame.SourceFile)2 ResourceResolver (com.android.ide.common.resources.ResourceResolver)2 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)2 RepositoryPackages (com.android.repository.impl.meta.RepositoryPackages)2 ResourceFolderType (com.android.resources.ResourceFolderType)2 AndroidVersion (com.android.sdklib.AndroidVersion)2 IAndroidTarget (com.android.sdklib.IAndroidTarget)2 GradleBuildFile (com.android.tools.idea.gradle.parser.GradleBuildFile)2 AndroidModuleModel (com.android.tools.idea.gradle.project.model.AndroidModuleModel)2 AndroidModuleInfo (com.android.tools.idea.model.AndroidModuleInfo)2 EditorDesignSurface (com.android.tools.idea.ui.designer.EditorDesignSurface)2