dea插件开发-自定义语言9-Rename Refactoring

        Rename 重构操作与Find Usages的重构操作非常相似。它使用相同的规则来定位要重命名的元素,并使用相同的单词索引来查找可能引用了被重命名元素的文件。执行重命名重构时,调用方法PsiNamedElement.setName()会为重命名的元素,调用该方法PsiReference.handleElementRename()为所有对重命名元素的引用。

        这些方法基本上执行相同的操作:将 PSI 元素的底层 AST 节点替换为包含用户输入的新文本的节点。从头开始创建一个完全正确的 AST 节点非常棘手。因此,获得替换节点的最简单方法是用自定义语言创建一个虚拟文件,以便它在其解析树中包含必要的节点,构建解析树并从中提取所需的节点。

public class PropertyImpl extends PropertiesStubElementImpl<PropertyStub> implements Property, PsiLanguageInjectionHost, PsiNameIdentifierOwner {private static final Logger LOG = Logger.getInstance(PropertyImpl.class);private static final Pattern PROPERTIES_SEPARATOR = Pattern.compile("^\\s*\\n\\s*\\n\\s*$");public PropertyImpl(@NotNull ASTNode node) {super(node);}public PropertyImpl(final PropertyStub stub, final IStubElementType nodeType) {super(stub, nodeType);}@Overridepublic String toString() {return "Property{ key = " + getKey() + ", value = " + getValue() + "}";}@Overridepublic PsiElement setName(@NotNull String name) throws IncorrectOperationException {PropertyImpl property = (PropertyImpl)PropertiesElementFactory.createProperty(getProject(), name, "xxx", null);ASTNode keyNode = getKeyNode();ASTNode newKeyNode = property.getKeyNode();LOG.assertTrue(newKeyNode != null);if (keyNode == null) {getNode().addChild(newKeyNode);}else {getNode().replaceChild(keyNode, newKeyNode);}return this;}@Overridepublic void setValue(@NotNull String value) throws IncorrectOperationException {setValue(value, PropertyKeyValueFormat.PRESENTABLE);}@Overridepublic void setValue(@NotNull String value, @NotNull PropertyKeyValueFormat format) throws IncorrectOperationException {ASTNode node = getValueNode();PropertyImpl property = (PropertyImpl)PropertiesElementFactory.createProperty(getProject(), "xxx", value, getKeyValueDelimiter(), format);ASTNode valueNode = property.getValueNode();if (node == null) {if (valueNode != null) {getNode().addChild(valueNode);}}else {if (valueNode == null) {getNode().removeChild(node);}else {getNode().replaceChild(node, valueNode);}}}@Overridepublic String getName() {return getUnescapedKey();}@Overridepublic String getKey() {final PropertyStub stub = getStub();if (stub != null) {return stub.getKey();}final ASTNode node = getKeyNode();if (node == null) {return null;}return node.getText();}@Nullablepublic ASTNode getKeyNode() {return getNode().findChildByType(PropertiesTokenTypes.KEY_CHARACTERS);}@Nullablepublic ASTNode getValueNode() {return getNode().findChildByType(PropertiesTokenTypes.VALUE_CHARACTERS);}@Overridepublic String getValue() {final ASTNode node = getValueNode();if (node == null) {return "";}return node.getText();}@Override@Nullablepublic String getUnescapedValue() {return unescape(getValue());}@Overridepublic @Nullable PsiElement getNameIdentifier() {final ASTNode node = getKeyNode();return node == null ? null : node.getPsi();}public static String unescape(String s) {if (s == null) return null;StringBuilder sb = new StringBuilder();parseCharacters(s, sb, null);return sb.toString();}public static boolean parseCharacters(String s, StringBuilder outChars, int @Nullable [] sourceOffsets) {assert sourceOffsets == null || sourceOffsets.length == s.length() + 1;int off = 0;int len = s.length();boolean result = true;final int outOffset = outChars.length();while (off < len) {char aChar = s.charAt(off++);if (sourceOffsets != null) {sourceOffsets[outChars.length() - outOffset] = off - 1;sourceOffsets[outChars.length() + 1 - outOffset] = off;}if (aChar == '\\') {aChar = s.charAt(off++);if (aChar == 'u') {// Read the xxxxint value = 0;boolean error = false;for (int i = 0; i < 4 && off < s.length(); i++) {aChar = s.charAt(off++);switch (aChar) {case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> value = (value << 4) + aChar - '0';case 'a', 'b', 'c', 'd', 'e', 'f' -> value = (value << 4) + 10 + aChar - 'a';case 'A', 'B', 'C', 'D', 'E', 'F' -> value = (value << 4) + 10 + aChar - 'A';default -> {outChars.append("\\u");int start = off - i - 1;int end = Math.min(start + 4, s.length());outChars.append(s, start, end);i = 4;error = true;off = end;}}}if (!error) {outChars.append((char)value);}else {result = false;}}else if (aChar == '\n') {// escaped linebreak: skip whitespace in the beginning of next linewhile (off < len && (s.charAt(off) == ' ' || s.charAt(off) == '\t')) {off++;}}else if (aChar == 't') {outChars.append('\t');}else if (aChar == 'r') {outChars.append('\r');}else if (aChar == 'n') {outChars.append('\n');}else if (aChar == 'f') {outChars.append('\f');}else {outChars.append(aChar);}}else {outChars.append(aChar);}if (sourceOffsets != null) {sourceOffsets[outChars.length() - outOffset] = off;}}return result;}@Nullablepublic static TextRange trailingSpaces(String s) {if (s == null) {return null;}int off = 0;int len = s.length();int startSpaces = -1;while (off < len) {char aChar = s.charAt(off++);if (aChar == '\\') {if (startSpaces == -1) startSpaces = off-1;aChar = s.charAt(off++);if (aChar == 'u') {// Read the xxxxint value = 0;boolean error = false;for (int i = 0; i < 4; i++) {aChar = off < s.length() ? s.charAt(off++) : 0;switch (aChar) {case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> value = (value << 4) + aChar - '0';case 'a', 'b', 'c', 'd', 'e', 'f' -> value = (value << 4) + 10 + aChar - 'a';case 'A', 'B', 'C', 'D', 'E', 'F' -> value = (value << 4) + 10 + aChar - 'A';default -> {int start = off - i - 1;int end = Math.min(start + 4, s.length());i = 4;error = true;off = end;startSpaces = -1;}}}if (!error) {if (Character.isWhitespace(value)) {if (startSpaces == -1) {startSpaces = off-1;}}else {startSpaces = -1;}}}else if (aChar == '\n') {// escaped linebreak: skip whitespace in the beginning of next linewhile (off < len && (s.charAt(off) == ' ' || s.charAt(off) == '\t')) {off++;}}else if (aChar == 't' || aChar == 'r') {if (startSpaces == -1) startSpaces = off;}else {if (aChar == 'n' || aChar == 'f') {if (startSpaces == -1) startSpaces = off;}else {if (Character.isWhitespace(aChar)) {if (startSpaces == -1) {startSpaces = off-1;}}else {startSpaces = -1;}}}}else {if (Character.isWhitespace(aChar)) {if (startSpaces == -1) {startSpaces = off-1;}}else {startSpaces = -1;}}}return startSpaces == -1 ? null : new TextRange(startSpaces, len);}@Override@Nullablepublic String getUnescapedKey() {return unescape(getKey());}@Nullable@Overrideprotected Icon getElementIcon(@IconFlags int flags) {return PlatformIcons.PROPERTY_ICON;}@Overridepublic void delete() throws IncorrectOperationException {final ASTNode parentNode = getParent().getNode();assert parentNode != null;ASTNode node = getNode();ASTNode prev = node.getTreePrev();ASTNode next = node.getTreeNext();parentNode.removeChild(node);if ((prev == null || prev.getElementType() == TokenType.WHITE_SPACE) && next != null &&next.getElementType() == TokenType.WHITE_SPACE) {parentNode.removeChild(next);}}@Overridepublic PropertiesFile getPropertiesFile() {PsiFile containingFile = super.getContainingFile();if (!(containingFile instanceof PropertiesFile)) {LOG.error("Unexpected file type of: " + containingFile.getName());}return (PropertiesFile)containingFile;}/*** The method gets the upper edge of a {@link Property} instance which might either be* the property itself or the first {@link PsiComment} node that is related to the property** @param property the property to get the upper edge for* @return the property itself or the first {@link PsiComment} node that is related to the property*/static PsiElement getEdgeOfProperty(@NotNull final Property property) {PsiElement prev = property;for (PsiElement node = property.getPrevSibling(); node != null; node = node.getPrevSibling()) {if (node instanceof Property) break;if (node instanceof PsiWhiteSpace) {if (PROPERTIES_SEPARATOR.matcher(node.getText()).find()) break;}prev = node;}return prev;}@Overridepublic String getDocCommentText() {final PsiElement edge = getEdgeOfProperty(this);StringBuilder text = new StringBuilder();for(PsiElement doc = edge; doc != this; doc = doc.getNextSibling()) {if (doc instanceof PsiComment) {text.append(doc.getText());text.append("\n");}}if (text.length() == 0) return null;return text.toString();}@NotNull@Overridepublic PsiElement getPsiElement() {return this;}@Override@NotNullpublic SearchScope getUseScope() {// property ref can occur in any filereturn GlobalSearchScope.allScope(getProject());}@Overridepublic ItemPresentation getPresentation() {return new ItemPresentation() {@Overridepublic String getPresentableText() {return getName();}@Overridepublic String getLocationString() {return getPropertiesFile().getName();}@Overridepublic Icon getIcon(final boolean open) {return null;}};}@Overridepublic boolean isValidHost() {return true;}@Overridepublic PsiLanguageInjectionHost updateText(@NotNull String text) {return new PropertyManipulator().handleContentChange(this, text);}@NotNull@Overridepublic LiteralTextEscaper<? extends PsiLanguageInjectionHost> createLiteralTextEscaper() {return new PropertyImplEscaper(this);}public char getKeyValueDelimiter() {final PsiElement delimiter = findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR);if (delimiter == null) {return ' ';}final String text = delimiter.getText();LOG.assertTrue(text.length() == 1);return text.charAt(0);}public void replaceKeyValueDelimiterWithDefault() {PropertyImpl property = (PropertyImpl)PropertiesElementFactory.createProperty(getProject(), "yyy", "xxx", null);final ASTNode newDelimiter = property.getNode().findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR);final ASTNode propertyNode = getNode();final ASTNode oldDelimiter = propertyNode.findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR);if (areDelimitersEqual(newDelimiter, oldDelimiter)) {return;}if (newDelimiter == null) {propertyNode.replaceChild(oldDelimiter, ASTFactory.whitespace(" "));} else {if (oldDelimiter == null) {propertyNode.addChild(newDelimiter, getValueNode());final ASTNode insertedDelimiter = propertyNode.findChildByType(PropertiesTokenTypes.KEY_VALUE_SEPARATOR);LOG.assertTrue(insertedDelimiter != null);ASTNode currentPrev = insertedDelimiter.getTreePrev();final List<ASTNode> toDelete = new ArrayList<>();while (currentPrev != null && currentPrev.getElementType() == PropertiesTokenTypes.WHITE_SPACE) {toDelete.add(currentPrev);currentPrev = currentPrev.getTreePrev();}for (ASTNode node : toDelete) {propertyNode.removeChild(node);}} else {propertyNode.replaceChild(oldDelimiter, newDelimiter);}}}private static boolean areDelimitersEqual(@Nullable ASTNode node1, @Nullable ASTNode node2) {if (node1 == null && node2 == null) return true;if (node1 == null || node2 == null) return false;final String text1 = node1.getText();final String text2 = node2.getText();return text1.equals(text2);}
}


        如果重命名的引用扩展了PsiReferenceBase,则调用ElementManipulator.handleContentChange()来执行重命名,负责处理内容更改并计算元素内引用的文本范围。要禁用特定元素的重命名,请实现com.intellij.openapi.util.Condition<T>PsiElement 类型T并将其注册到com.intellij.vetoRenameCondition扩展点。

一、名称验证

        NamesValidatorRename允许插件根据自定义语言规则检查用户在对话框中输入的名称是否是有效标识符(而不是关键字)。如果插件未提供此接口的实现,则使用用于验证标识符的 Java 规则。的实现NamesValidator在扩展点中注册com.intellij.lang.namesValidator。

public class PropertiesNamesValidator implements NamesValidator {@Overridepublic boolean isKeyword(@NotNull final String name, final Project project) {return false;}@Overridepublic boolean isIdentifier(@NotNull final String name, final Project project) {return true;}
}

        另一种检查方式是RenameInputValidator,不像NamesValidator它允许您更灵活地根据方法中定义的规则检查输入的名称是否正确isInputValid()。要确定此验证器将应用于哪些元素,请覆盖getPattern()返回要验证的元素模式的方法。比如以下示例:

public class YAMLAnchorRenameInputValidator implements RenameInputValidator {@NotNull@Overridepublic ElementPattern<? extends PsiElement> getPattern() {return psiElement(YAMLAnchor.class);}@Overridepublic boolean isInputValid(@NotNull String newName, @NotNull PsiElement element, @NotNull ProcessingContext context) {return newName.matches("[^,\\[\\]{}\\n\\t ]+");}
}

        RenameInputValidator可以扩展为RenameInputValidatorEx覆盖默认错误消息。getErrorMessage()如果名称无效或其他情况,该方法应返回自定义错误消息null。请注意,getErrorMessage()仅当所有人都RenameInputValidator接受新名称isInputValid()并且该名称是元素语言的有效标识符时才有效,这种方式需要实现com.intellij.renameInputValidator扩展点。

public final class YamlKeyValueRenameInputValidator implements RenameInputValidatorEx {private static final String IDENTIFIER_START_PATTERN = "(([^\\n\\t\\r \\-?:,\\[\\]{}#&*!|>'\"%@`])" +"|([?:-][^\\n\\t\\r ])" +")";private static final String IDENTIFIER_END_PATTERN = "(([^\\n\\t\\r ]#)" +"|([^\\n\\t\\r :#])" +"|(:[^\\n\\t\\r ])" +")";// Taken from yaml.flex, NS_PLAIN_ONE_LINE_block. This may not be entirely correct, but it is less restrictive than the default names// validatorpublic static final Pattern IDENTIFIER_PATTERN = Pattern.compile("(" + IDENTIFIER_START_PATTERN + "([ \t]*" + IDENTIFIER_END_PATTERN + ")*)|" +"('[^\\n']*')|(\"[^\\n\"]*\")");@Nullable@Overridepublic String getErrorMessage(@NotNull final String newName, @NotNull final Project project) {return IDENTIFIER_PATTERN.matcher(newName).matches() ? null : YAMLBundle.message("rename.invalid.name", newName);}@NotNull@Overridepublic ElementPattern<? extends PsiElement> getPattern() {return PlatformPatterns.psiElement(YAMLKeyValue.class);}@Overridepublic boolean isInputValid(@NotNull final String newName, @NotNull final PsiElement element, @NotNull final ProcessingContext context) {return true;}
}

二、自定义重命名UI和工作流程

        可以在多个级别进一步自定义重命名重构处理。提供接口的自定义实现RenameHandler允许您完全替换 rename 重构的 UI 和工作流,并且还支持重命名根本不是PsiElement的元素。示例:用于在Properties 语言插件RenameHandler中重命名资源包

public class ResourceBundleFromEditorRenameHandler implements RenameHandler {@Overridepublic boolean isAvailableOnDataContext(@NotNull DataContext dataContext) {final Project project = CommonDataKeys.PROJECT.getData(dataContext);if (project == null) {return false;}final ResourceBundle bundle = ResourceBundleUtil.getResourceBundleFromDataContext(dataContext);if (bundle == null) {return false;}final FileEditor fileEditor = PlatformCoreDataKeys.FILE_EDITOR.getData(dataContext);if (!(fileEditor instanceof ResourceBundleEditor)) {return false;}final VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);return virtualFile instanceof ResourceBundleAsVirtualFile;}@Overridepublic void invoke(final @NotNull Project project, Editor editor, final PsiFile file, DataContext dataContext) {final ResourceBundleEditor resourceBundleEditor = (ResourceBundleEditor)PlatformCoreDataKeys.FILE_EDITOR.getData(dataContext);assert resourceBundleEditor != null;final Object selectedElement = resourceBundleEditor.getSelectedElementIfOnlyOne();if (selectedElement != null) {CommandProcessor.getInstance().runUndoTransparentAction(() -> {if (selectedElement instanceof PropertiesPrefixGroup group) {ResourceBundleRenameUtil.renameResourceBundleKeySection(getPsiElementsFromGroup(group),group.getPresentableName(),group.getPrefix().length() - group.getPresentableName().length());} else if (selectedElement instanceof PropertyStructureViewElement) {final PsiElement psiElement = ((PropertyStructureViewElement)selectedElement).getPsiElement();ResourceBundleRenameUtil.renameResourceBundleKey(psiElement, project);} else if (selectedElement instanceof ResourceBundleFileStructureViewElement) {ResourceBundleRenameUtil.renameResourceBundleBaseName(((ResourceBundleFileStructureViewElement)selectedElement).getValue(), project);} else {throw new IllegalStateException("unsupported type: " + selectedElement.getClass());}});}}@Overridepublic void invoke(@NotNull Project project, PsiElement @NotNull [] elements, DataContext dataContext) {invoke(project, null, null, dataContext);}private static List<PsiElement> getPsiElementsFromGroup(final PropertiesPrefixGroup propertiesPrefixGroup) {return ContainerUtil.mapNotNull(propertiesPrefixGroup.getChildren(), treeElement -> {if (treeElement instanceof PropertyStructureViewElement) {return ((PropertyStructureViewElement)treeElement).getPsiElement();}return null;});

如果您对标准 UI 没问题但需要扩展重命名的默认逻辑,您可以提供接口的实现RenamePsiElementProcessor,以实现以下功能:

1、重命名与调用操作的元素不同的元素(例如,超级方法)

2、一次重命名多个元素(如果它们的名称根据您的语言逻辑链接)

3、检查名称冲突(现有名称等)

4、自定义搜索代码参考或文本参考的方式

示例:用于重命名Properties 插件语言RenamePsiElementProcessor中的属性

public abstract class RenamePsiElementProcessor extends RenamePsiElementProcessorBase {@NotNullpublic RenameDialog createRenameDialog(@NotNull Project project,@NotNull PsiElement element,@Nullable PsiElement nameSuggestionContext,@Nullable Editor editor) {return new RenameDialog(project, element, nameSuggestionContext, editor);}@Overridepublic RenameRefactoringDialog createDialog(@NotNull Project project,@NotNull PsiElement element,@Nullable PsiElement nameSuggestionContext,@Nullable Editor editor) {return this.createRenameDialog(project, element, nameSuggestionContext, editor);}@NotNullpublic static RenamePsiElementProcessor forElement(@NotNull PsiElement element) {for (RenamePsiElementProcessorBase processor : EP_NAME.getExtensionList()) {if (processor.canProcessElement(element)) {return (RenamePsiElementProcessor)processor;}}return DEFAULT;}@NotNullpublic static List<RenamePsiElementProcessor> allForElement(@NotNull PsiElement element) {final List<RenamePsiElementProcessor> result = new ArrayList<>();for (RenamePsiElementProcessorBase processor : EP_NAME.getExtensions()) {if (processor.canProcessElement(element)) {result.add((RenamePsiElementProcessor)processor);}}return result;}private static class MyRenamePsiElementProcessor extends RenamePsiElementProcessor implements DefaultRenamePsiElementProcessor {@Overridepublic boolean canProcessElement(@NotNull final PsiElement element) {return true;}}public static final RenamePsiElementProcessor DEFAULT = new MyRenamePsiElementProcessor();
}

​三、示例实现

10. Reference Contributor | IntelliJ Platform Plugin SDK

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/54911.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Canvas与诗词】秋夕.杜牧(银烛秋光冷画屏......)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>金六边形外圈绿色底录杜牧秋夕诗</title><style type"…

AI学习指南深度学习篇-丢弃法Python实践

AI学习指南深度学习篇-丢弃法Python实践 引言 在深度学习的领域中&#xff0c;丢弃法&#xff08;Dropout&#xff09;是一种有效的防止过拟合的随机正则化技术。过拟合是指模型在训练集上表现良好&#xff0c;但在测试集或未见过的数据上表现较差的现象。丢弃法通过随机地“…

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术QueSearch

【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search 目录 文章目录 【电商搜索】现代工业级电商搜索技术-Facebook语义搜索技术Que2Search目录0. 论文信息1. 研究背景&#xff1a;2. 技术背景和发展历史&#xff1a;3. 算法建模3.1 模型架构3.1.1 双塔与分类 …

Rust调用tree-sitter支持自定义语言解析

要使用 Rust 调用 tree-sitter 解析自定义语言&#xff0c;你需要遵循一系列步骤来定义语言的语法&#xff0c;生成解析器&#xff0c;并在 Rust 中使用这个解析器。下面是详细步骤&#xff1a; 1. 定义自定义语言的语法 首先&#xff0c;你需要创建一个 tree-sitter 语言定义…

NLP:BERT的介绍

1. BERT 1.1 Transformer Transformer架构是一种基于自注意力机制(self-attention)的神经网络架构&#xff0c;它代替了以前流行的循环神经网络和长短期记忆网络&#xff0c;已经应用到多个自然语言处理方向。   Transformer架构由两个主要部分组成&#xff1a;编码器(Encod…

【HarmonyOS】应用引用media中的字符串资源如何拼接字符串

【HarmonyOS】应用引用media中的字符串资源如何拼接字符串 一、问题背景&#xff1a; 鸿蒙应用中使用字符串资源加载&#xff0c;一般文本放置在resoutces-base-element-string.json字符串配置文件中。便于国际化的处理。当然小项目一般直接引用字符串&#xff0c;不需要加载s…

[dp+dfs]砝码称重

题目描述 现有 n n n 个砝码&#xff0c;重量分别为 a 1 , a 2 , … , a n a_1, a_2, \ldots,a_n a1​,a2​,…,an​ &#xff0c;在去掉 m m m 个砝码后&#xff0c;问最多能称量出多少不同的重量&#xff08;不包括 0 0 0 &#xff09;。 输入格式 第一行为有两个整数…

python爬虫:从12306网站获取火车站信息

代码逻辑 初始化 (init 方法)&#xff1a; 设置请求头信息。设置车站版本号。 同步车站信息 (synchronization 方法)&#xff1a; 发送GET请求获取车站信息。返回服务器响应的文本。 提取信息 (extract 方法)&#xff1a; 从服务器响应中提取车站信息字符串。去掉字符串末尾的…

如何通过Dockfile更改docker中ubuntu的apt源

首先明确我们有一个宿主机和一个docker环境&#xff0c;接下来的步骤是基于他们两个完成的 1.在宿主机上创建Dockerfile 随便将后面创建的Dockerfile放在一个位置,我这里选择的是 /Desktop 使用vim前默认你已经安装好了vim 2.在输入命令“vim Dockerfile”之后&#xff0c;…

知识付费APP开发指南:基于在线教育系统源码的技术详解

本篇文章&#xff0c;我们将探讨基于在线教育系统源码的知识付费APP开发的技术细节&#xff0c;帮助开发者和企业快速入门。 一、选择合适的在线教育系统源码 选择合适的在线教育系统源码是开发的关键一步。市场上有许多开源和商业化的在线教育系统源码&#xff0c;开发者需要…

花都狮岭寄宿自闭症学校:开启孩子的生命之门

在花都狮岭这片充满温情的土地上&#xff0c;有一所特别的学校&#xff0c;它像一把钥匙&#xff0c;轻轻旋转&#xff0c;为自闭症儿童们开启了一扇通往无限可能的生命之门——这就是广州星贝育园自闭症儿童寄宿制学校。这所学校不仅是知识的摇篮&#xff0c;更是孩子们心灵成…

React 启动时webpack版本冲突报错

报错信息&#xff1a; 解决办法&#xff1a; 找到全局webpack的安装路径并cmd 删除全局webpack 安装所需要的版本

Python(六)-拆包,交换变量名,lambda

目录 拆包 交换变量值 引用 lambda函数 lambda实例 字典的lambda 推导式 列表推导式 列表推导式if条件判断 for循环嵌套列表推导式 字典推导式 集合推导式 拆包 看一下在Python程序中的拆包&#xff1a;把组合形成的元组形式的数据&#xff0c;拆分出单个元素内容…

影响上证50股指期货价格的因素有哪些?

上证50股指期货&#xff0c;作为反映上海证券交易所最具代表性50只股票整体表现的期货合约&#xff0c;其价格同样受到一系列复杂因素的驱动。以下是对影响上证50股指期货价格的主要因素进行的详细分析。 因素一、期货合约的供求关系 股指期货市场是一个由多头和空头双方共同…

具身智能综述:鹏城实验室中大调研近400篇文献,深度解析具身智能

具身智能是实现通用人工智能的必经之路&#xff0c;其核心是通过智能体与数字空间和物理世界的交互来完成复杂任务。近年来&#xff0c;多模态大模型和机器人技术得到了长足发展&#xff0c;具身智能成为全球科技和产业竞争的新焦点。然而&#xff0c;目前缺少一篇能够全面解析…

面试遇到的质量体系10个问题(深度思考)

在某大型公司的招聘面试中关于质量体系本身及建设实践方面的10个问题&#xff0c;这些问题都是偏理论性强一些&#xff0c;但是可以通过这些问题来了解大型公司对质量体系的一些想法和预期的内容&#xff0c;本期先抛出来这10个问题&#xff0c;不附答案&#xff0c;目的就是让…

AI绘画:Stable Diffusion 终极炼丹宝典:从入门到精通

前言 我是Lison&#xff0c;以浅显易懂的方式&#xff0c;与大家分享那些实实在在可行之宝藏。 历经耗时数十个小时&#xff0c;总算将这份Stable Diffusion的使用教程整理妥当。 从最初的安装与配置&#xff0c;细至界面功能的详解&#xff0c;再至实战案例的制作&#xff…

数组基础(c++)

第1题 精挑细选 时限&#xff1a;1s 空间&#xff1a;256m 小王是公司的仓库管理员&#xff0c;一天&#xff0c;他接到了这样一个任务&#xff1a;从仓库中找出一根钢管。这听起来不算什么&#xff0c;但是这根钢管的要求可真是让他犯难了&#xff0c;要求如下&#x…

从细胞到临床:表观组学分析技术在精准医疗中的角色

中国科学院等科研院所的顶尖人才发起&#xff0c;专注于多组学、互作组、生物医学等领域的研究与服务。在Nature等国际知名期刊发表多篇论文&#xff0c;提供实验整体打包、免费SCI论文润色等四大优势服务。在表观组学分析技术方面&#xff0c;提供DAP-seq、ATAC-seq、H3K4me3 …

使用mendeley生成APA格式参考文献

mendeley 是一款文献管理工具&#xff0c;可以在word中方便的插入引用文献。 效果对比&#xff1a; 注&#xff1a;小绿鲸有三种导出格式&#xff0c;分别为复制、导出为Bibtex和导出为Endnote三种。 mendeley 下载与安装 Download Mendeley Reference Manager For Desktop mac…