mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -40,7 +40,7 @@ public class RunLineMarkerProvider implements LineMarkerProvider {
|
||||
@Override
|
||||
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) {
|
||||
List<RunLineMarkerContributor> contributors = RunLineMarkerContributor.EXTENSION.allForLanguage(element.getLanguage());
|
||||
final DefaultActionGroup actionGroup = new DefaultActionGroup();
|
||||
DefaultActionGroup actionGroup = null;
|
||||
Icon icon = null;
|
||||
for (RunLineMarkerContributor contributor : contributors) {
|
||||
RunLineMarkerContributor.Info info = contributor.getInfo(element);
|
||||
@@ -50,6 +50,9 @@ public class RunLineMarkerProvider implements LineMarkerProvider {
|
||||
if (icon == null) {
|
||||
icon = info.icon;
|
||||
}
|
||||
if (actionGroup == null) {
|
||||
actionGroup = new DefaultActionGroup();
|
||||
}
|
||||
for (AnAction action : info.actions) {
|
||||
actionGroup.add(new LineMarkerActionWrapper(element, action));
|
||||
}
|
||||
@@ -57,7 +60,9 @@ public class RunLineMarkerProvider implements LineMarkerProvider {
|
||||
}
|
||||
if (icon == null) return null;
|
||||
|
||||
return new LineMarkerInfo<PsiElement>(element, element.getTextOffset(), icon, Pass.UPDATE_ALL, null, null, GutterIconRenderer.Alignment.CENTER) {
|
||||
final DefaultActionGroup finalActionGroup = actionGroup;
|
||||
return new LineMarkerInfo<PsiElement>(element, element.getTextOffset(), icon, Pass.UPDATE_ALL, null, null,
|
||||
GutterIconRenderer.Alignment.CENTER) {
|
||||
@Nullable
|
||||
@Override
|
||||
public GutterIconRenderer createGutterRenderer() {
|
||||
@@ -75,7 +80,7 @@ public class RunLineMarkerProvider implements LineMarkerProvider {
|
||||
@Nullable
|
||||
@Override
|
||||
public ActionGroup getPopupMenuActions() {
|
||||
return actionGroup;
|
||||
return finalActionGroup;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.ide;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -48,7 +45,10 @@ public class ReopenProjectAction extends AnAction implements DumbAware {
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final int modifiers = e.getModifiers();
|
||||
final boolean forceOpenInNewFrame = (modifiers & InputEvent.CTRL_MASK) != 0 || (modifiers & InputEvent.SHIFT_MASK) != 0;
|
||||
final boolean forceOpenInNewFrame = (modifiers & InputEvent.CTRL_MASK) != 0
|
||||
|| (modifiers & InputEvent.SHIFT_MASK) != 0
|
||||
|| e.getPlace() == ActionPlaces.WELCOME_SCREEN;
|
||||
|
||||
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
|
||||
if (!new File(myProjectPath).exists()) {
|
||||
if (Messages.showDialog(project, "The path " + FileUtil.toSystemDependentName(myProjectPath) + " does not exist.\n" +
|
||||
|
||||
@@ -266,8 +266,8 @@ public class ShowFilePathAction extends AnAction {
|
||||
|
||||
public static boolean isSupported() {
|
||||
return SystemInfo.isWindows ||
|
||||
Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN) ||
|
||||
SystemInfo.hasXdgOpen() || canUseNautilus.getValue();
|
||||
SystemInfo.hasXdgOpen() || canUseNautilus.getValue() ||
|
||||
Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -285,9 +285,7 @@ public class ShowFilePathAction extends AnAction {
|
||||
if (!file.exists()) return;
|
||||
file = file.getAbsoluteFile();
|
||||
File parent = file.getParentFile();
|
||||
if (parent == null) {
|
||||
return;
|
||||
}
|
||||
if (parent == null) return;
|
||||
try {
|
||||
doOpen(parent, file);
|
||||
}
|
||||
|
||||
+6
-4
@@ -134,10 +134,12 @@ public class RecentProjectPanel extends JPanel {
|
||||
myList.registerKeyboardAction(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Object selection = myList.getSelectedValue();
|
||||
|
||||
if (selection != null) {
|
||||
((AnAction)selection).actionPerformed(AnActionEvent.createFromInputEvent((AnAction)selection, null, ActionPlaces.WELCOME_SCREEN));
|
||||
final Object[] selectedValued = myList.getSelectedValues();
|
||||
if (selectedValued != null) {
|
||||
for (Object selection : selectedValued) {
|
||||
AnActionEvent event = AnActionEvent.createFromInputEvent((AnAction)selection, null, ActionPlaces.WELCOME_SCREEN);
|
||||
((AnAction)selection).actionPerformed(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
|
||||
|
||||
@@ -113,22 +113,22 @@ public class SystemInfo extends SystemInfoRt {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Boolean compute() {
|
||||
return isUnix && new File("/usr/bin/xdg-open").canExecute();
|
||||
return new File("/usr/bin/xdg-open").canExecute();
|
||||
}
|
||||
};
|
||||
public static boolean hasXdgOpen() {
|
||||
return ourHasXdgOpen.getValue();
|
||||
return isXWindow && ourHasXdgOpen.getValue();
|
||||
}
|
||||
|
||||
private static final NotNullLazyValue<Boolean> ourHasXdgMime = new AtomicNotNullLazyValue<Boolean>() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected Boolean compute() {
|
||||
return isUnix && new File("/usr/bin/xdg-mime").canExecute();
|
||||
return new File("/usr/bin/xdg-mime").canExecute();
|
||||
}
|
||||
};
|
||||
public static boolean hasXdgMime() {
|
||||
return ourHasXdgOpen.getValue();
|
||||
return isXWindow && ourHasXdgMime.getValue();
|
||||
}
|
||||
|
||||
public static final boolean isMacOSTiger = isMac && isOsVersionAtLeast("10.4");
|
||||
|
||||
@@ -97,7 +97,7 @@ public abstract class ShowChangeMarkerAction extends AbstractVcsAction {
|
||||
@Override
|
||||
protected void update(VcsContext context, Presentation presentation) {
|
||||
LineStatusTracker tracker = myChangeMarkerContext.getLineStatusTracker(context);
|
||||
if (tracker == null || tracker.isSilentMode()) {
|
||||
if (tracker == null || tracker.isReleased() || tracker.isSilentMode()) {
|
||||
presentation.setEnabledAndVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public abstract class BaseLineStatusRangeAction extends AnAction implements Dumb
|
||||
}
|
||||
|
||||
public void update(final AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(!myLineStatusTracker.isSilentMode() && isEnabled());
|
||||
e.getPresentation().setEnabled(!myLineStatusTracker.isSilentMode() && !myLineStatusTracker.isReleased() && isEnabled());
|
||||
}
|
||||
|
||||
public abstract boolean isEnabled();
|
||||
|
||||
@@ -231,6 +231,12 @@ public class LineStatusTracker {
|
||||
return highlighter;
|
||||
}
|
||||
|
||||
public boolean isReleased() {
|
||||
synchronized (myLock) {
|
||||
return myReleased;
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
synchronized (myLock) {
|
||||
myReleased = true;
|
||||
@@ -832,7 +838,7 @@ public class LineStatusTracker {
|
||||
myApplication.assertWriteAccessAllowed();
|
||||
|
||||
synchronized (myLock) {
|
||||
if (myBulkUpdate) return;
|
||||
if (myReleased || myBulkUpdate || mySuppressUpdate || myAnathemaThrown) return;
|
||||
|
||||
try {
|
||||
mySuppressUpdate = true;
|
||||
|
||||
@@ -215,6 +215,7 @@ public class LineStatusTrackerDrawing {
|
||||
@NotNull Editor editor,
|
||||
@NotNull LineStatusTracker tracker,
|
||||
@Nullable Point mousePosition) {
|
||||
if (tracker.isReleased()) return;
|
||||
final Disposable disposable = Disposer.newDisposable();
|
||||
|
||||
List<DiffFragment> wordDiff = computeWordDiff(range, tracker);
|
||||
@@ -385,6 +386,7 @@ public class LineStatusTrackerDrawing {
|
||||
}
|
||||
|
||||
public static void moveToRange(final Range range, final Editor editor, final LineStatusTracker tracker) {
|
||||
if (tracker.isReleased()) return;
|
||||
final Document document = tracker.getDocument();
|
||||
int line = Math.min(range.getType() == Range.DELETED ? range.getLine2() : range.getLine2() - 1, getLineCount(document) - 1);
|
||||
final int lastOffset = document.getLineStartOffset(line);
|
||||
|
||||
@@ -45,7 +45,7 @@ public class RollbackLineStatusAction extends DumbAwareAction {
|
||||
return;
|
||||
}
|
||||
LineStatusTracker tracker = LineStatusTrackerManager.getInstance(project).getLineStatusTracker(editor.getDocument());
|
||||
if (tracker == null || tracker.isSilentMode()) {
|
||||
if (tracker == null || tracker.isReleased() || tracker.isSilentMode()) {
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 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.
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.idea.devkit.dom.impl;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xml.ConvertContext;
|
||||
import com.intellij.util.xml.ResolvingConverter;
|
||||
@@ -55,6 +56,12 @@ class LanguageResolvingConverter extends ResolvingConverter<LanguageResolvingUti
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement getPsiElement(@Nullable LanguageResolvingUtil.LanguageDefinition resolvedValue) {
|
||||
return resolvedValue != null ? resolvedValue.clazz : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String toString(@Nullable LanguageResolvingUtil.LanguageDefinition o, ConvertContext context) {
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.internal;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
@@ -24,17 +26,23 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class IconsGeneratedSourcesFilter extends GeneratedSourcesFilter {
|
||||
@Override
|
||||
public boolean isGeneratedSource(@NotNull VirtualFile file, @NotNull Project project) {
|
||||
public boolean isGeneratedSource(@NotNull final VirtualFile file, @NotNull final Project project) {
|
||||
if (file.getName().endsWith("Icons.java")) {
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile instanceof PsiJavaFile) {
|
||||
for (PsiClass aClass : ((PsiJavaFile)psiFile).getClasses()) {
|
||||
if (aClass.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
PsiDocComment comment = aClass.getDocComment();
|
||||
return comment != null && comment.getText().contains("run build/scripts/icons.gant instead");
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile instanceof PsiJavaFile) {
|
||||
for (PsiClass aClass : ((PsiJavaFile)psiFile).getClasses()) {
|
||||
if (aClass.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
PsiDocComment comment = aClass.getDocComment();
|
||||
return comment != null && comment.getText().contains("run build/scripts/icons.gant instead");
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+14
-1
@@ -16,7 +16,10 @@
|
||||
package org.jetbrains.plugins.gradle.execution.test.runner.events;
|
||||
|
||||
import com.intellij.execution.testframework.sm.runner.SMTestProxy;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsoleManager;
|
||||
import org.jetbrains.plugins.gradle.util.XmlXpathHelper;
|
||||
|
||||
@@ -67,7 +70,17 @@ public class AfterTestEvent extends AbstractTestEvent {
|
||||
if ("comparison".equals(failureType)) {
|
||||
String actualText = eventXml.queryXml("/ijLog/event/test/result/actual");
|
||||
String expectedText = eventXml.queryXml("/ijLog/event/test/result/expected");
|
||||
testProxy.setTestComparisonFailed(exceptionMsg, stackTrace, actualText, expectedText);
|
||||
final Condition<String> emptyString = new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String s) {
|
||||
return StringUtil.isEmpty(s);
|
||||
}
|
||||
};
|
||||
String filePath = ObjectUtils.nullizeByCondition(
|
||||
eventXml.queryXml("/ijLog/event/test/result/filePath"), emptyString);
|
||||
String actualFilePath = ObjectUtils.nullizeByCondition(
|
||||
eventXml.queryXml("/ijLog/event/test/result/actualFilePath"), emptyString);
|
||||
testProxy.setTestComparisonFailed(exceptionMsg, stackTrace, actualText, expectedText, filePath, actualFilePath);
|
||||
}
|
||||
else {
|
||||
Couple<String> comparisonPair =
|
||||
|
||||
+29
-3
@@ -53,6 +53,11 @@ gradle.taskGraph.beforeTask { Task task ->
|
||||
|
||||
if (task instanceof Test) {
|
||||
try {
|
||||
def urls = task.classpath.files.findAll{
|
||||
it.name.equals('idea_rt.jar') || it.name.startsWith('junit')
|
||||
}.collect { it.toURI().toURL()}
|
||||
Class.forName("org.gradle.launcher.daemon.bootstrap.DaemonMain").getClassLoader().addURLs(urls)
|
||||
|
||||
logTestReportLocation(task.reports?.html?.entryPoint?.path)
|
||||
|
||||
task.beforeSuite { descriptor ->
|
||||
@@ -112,12 +117,33 @@ Object logTestEvent(def testEventType, TestDescriptorInternal testDescriptor, de
|
||||
failureType('comparison')
|
||||
xml.mkp.yieldUnescaped("<expected>$expected</expected>")
|
||||
xml.mkp.yieldUnescaped("<actual>$actual</actual>")
|
||||
} else if('junit.framework.AssertionFailedError'.equals(testResult.exception?.class?.name) ||
|
||||
return
|
||||
}
|
||||
try {
|
||||
if ('com.intellij.rt.execution.junit.FileComparisonFailure'.equals(testResult.exception?.class?.name)) {
|
||||
def expected = escapeCdata(testResult.exception.expected)
|
||||
def actual = escapeCdata(testResult.exception.actual)
|
||||
def filePath = escapeCdata(testResult.exception.filePath)
|
||||
def actualFilePath
|
||||
if (testResult.exception.hasProperty('actualFilePath')) {
|
||||
actualFilePath = escapeCdata(testResult.exception.actualFilePath)
|
||||
}
|
||||
failureType('comparison')
|
||||
xml.mkp.yieldUnescaped("<expected>$expected</expected>")
|
||||
xml.mkp.yieldUnescaped("<actual>$actual</actual>")
|
||||
xml.mkp.yieldUnescaped("<filePath>$filePath</filePath>")
|
||||
if (actualFilePath) xml.mkp.yieldUnescaped("<actualFilePath>$actualFilePath</actualFilePath>")
|
||||
return
|
||||
}
|
||||
}
|
||||
catch (ignore) {
|
||||
}
|
||||
if ('junit.framework.AssertionFailedError'.equals(testResult.exception?.class?.name) ||
|
||||
testResult.exception instanceof AssertionError) {
|
||||
failureType('assertionFailed')
|
||||
} else {
|
||||
failureType('error')
|
||||
return
|
||||
}
|
||||
failureType('error')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-6
@@ -1,18 +1,19 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package com.jetbrains.commandInterface.commandLine.psi.impl;
|
||||
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.*;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*;
|
||||
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
|
||||
import com.jetbrains.commandInterface.commandLine.psi.*;
|
||||
import com.jetbrains.commandInterface.command.Argument;
|
||||
import com.jetbrains.commandInterface.command.Help;
|
||||
import com.jetbrains.commandInterface.command.Option;
|
||||
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
|
||||
import com.jetbrains.commandInterface.commandLine.psi.CommandLineArgument;
|
||||
import com.jetbrains.commandInterface.commandLine.psi.CommandLineVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*;
|
||||
|
||||
public class CommandLineArgumentImpl extends CommandLineElement implements CommandLineArgument {
|
||||
|
||||
@@ -37,6 +38,12 @@ public class CommandLineArgumentImpl extends CommandLineElement implements Comma
|
||||
return findChildByType(LITERAL_STARTS_FROM_LETTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getLiteralStartsFromSymbol() {
|
||||
return findChildByType(LITERAL_STARTS_FROM_SYMBOL);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Option findOptionForOptionArgument() {
|
||||
return CommandLinePsiImplUtils.findOptionForOptionArgument(this);
|
||||
|
||||
-62
@@ -1,62 +0,0 @@
|
||||
// This is a generated file. Not intended for manual editing.
|
||||
package com.jetbrains.commandInterface.commandLine.psi.impl;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.jetbrains.commandInterface.command.Argument;
|
||||
import com.jetbrains.commandInterface.command.Help;
|
||||
import com.jetbrains.commandInterface.command.Option;
|
||||
import com.jetbrains.commandInterface.commandLine.CommandLineElement;
|
||||
import com.jetbrains.commandInterface.commandLine.psi.CommandLineArgument;
|
||||
import com.jetbrains.commandInterface.commandLine.psi.CommandLineVisitor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.jetbrains.commandInterface.commandLine.CommandLineElementTypes.*;
|
||||
|
||||
public class CommandLineArgumentImpl extends CommandLineElement implements CommandLineArgument {
|
||||
|
||||
public CommandLineArgumentImpl(ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
public void accept(@NotNull PsiElementVisitor visitor) {
|
||||
if (visitor instanceof CommandLineVisitor) ((CommandLineVisitor)visitor).visitArgument(this);
|
||||
else super.accept(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getLiteralStartsFromDigit() {
|
||||
return findChildByType(LITERAL_STARTS_FROM_DIGIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getLiteralStartsFromLetter() {
|
||||
return findChildByType(LITERAL_STARTS_FROM_LETTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public PsiElement getLiteralStartsFromSymbol() {
|
||||
return findChildByType(LITERAL_STARTS_FROM_SYMBOL);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Option findOptionForOptionArgument() {
|
||||
return CommandLinePsiImplUtils.findOptionForOptionArgument(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Argument findRealArgument() {
|
||||
return CommandLinePsiImplUtils.findRealArgument(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Help findBestHelp() {
|
||||
return CommandLinePsiImplUtils.findBestHelp(this);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user